ETH Price: $3,907.17 (-0.83%)

Contract

0x0000000000DfEd903aD76996FC07BF89C0127B1E
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Cancel Account R...124305692021-05-14 5:10:091309 days ago1620969009IN
0x00000000...9C0127B1E
0 ETH0.0033235296.6
Cancel Account R...115572062020-12-30 19:04:571443 days ago1609355097IN
0x00000000...9C0127B1E
0 ETH0.00281473105
Cancel Account R...113219542020-11-24 15:57:261479 days ago1606233446IN
0x00000000...9C0127B1E
0 ETH0.00370121138.1
Recover112246302020-11-09 17:19:511494 days ago1604942391IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112246292020-11-09 17:19:311494 days ago1604942371IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112246282020-11-09 17:19:121494 days ago1604942352IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112246252020-11-09 17:18:341494 days ago1604942314IN
0x00000000...9C0127B1E
0 ETH0.0030098152
Recover112246222020-11-09 17:17:451494 days ago1604942265IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112246212020-11-09 17:17:161494 days ago1604942236IN
0x00000000...9C0127B1E
0 ETH0.0030098152
Recover112246172020-11-09 17:16:591494 days ago1604942219IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112246132020-11-09 17:16:221494 days ago1604942182IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112246112020-11-09 17:15:331494 days ago1604942133IN
0x00000000...9C0127B1E
0 ETH0.0030098152
Recover112246092020-11-09 17:14:481494 days ago1604942088IN
0x00000000...9C0127B1E
0 ETH0.0030098152
Recover112246042020-11-09 17:14:081494 days ago1604942048IN
0x00000000...9C0127B1E
0 ETH0.0022291852
Recover112246012020-11-09 17:13:381494 days ago1604942018IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245992020-11-09 17:12:541494 days ago1604941974IN
0x00000000...9C0127B1E
0 ETH0.0023198654.1
Recover112245962020-11-09 17:12:021494 days ago1604941922IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245942020-11-09 17:11:251494 days ago1604941885IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245932020-11-09 17:11:051494 days ago1604941865IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245912020-11-09 17:10:541494 days ago1604941854IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245862020-11-09 17:09:431494 days ago1604941783IN
0x00000000...9C0127B1E
0 ETH0.0030098152
Recover112245852020-11-09 17:09:061494 days ago1604941746IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245822020-11-09 17:08:001494 days ago1604941680IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245802020-11-09 17:07:171494 days ago1604941637IN
0x00000000...9C0127B1E
0 ETH0.0022298152
Recover112245792020-11-09 17:07:051494 days ago1604941625IN
0x00000000...9C0127B1E
0 ETH0.0030091852
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
90783962019-12-09 16:34:281830 days ago1575909268  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DharmaAccountRecoveryManagerV2

Compiler Version
v0.5.11+commit.c082d0b4

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2019-12-09
*/

pragma solidity 0.5.11; // optimization runs: 200, evm version: petersburg


interface DharmaAccountRecoveryManagerInterface {
  // Fires an event whenever a user signing key is recovered for an account.
  event Recovery(
    address indexed wallet, address oldUserSigningKey, address newUserSigningKey
  );

  // Fire an event whenever account recovery is disabled for an account.
  event RecoveryDisabled(address wallet);

  function initiateAccountRecovery(
    address smartWallet, address userSigningKey, uint256 extraTime
  ) external;

  function initiateAccountRecoveryDisablement(
    address smartWallet, uint256 extraTime
  ) external;

  function recover(address wallet, address newUserSigningKey) external;

  function disableAccountRecovery(address wallet) external;

  function accountRecoveryDisabled(
    address wallet
  ) external view returns (bool hasDisabledAccountRecovery);
}


interface DharmaAccountRecoveryManagerV2Interface {
  // Fires an event whenever a pending account recovery is cancelled.
  event RecoveryCancelled(
    address indexed wallet, address cancelledUserSigningKey
  );

  event RecoveryDisablementCancelled(address wallet);

  event RoleModified(Role indexed role, address account);

  event RolePaused(Role indexed role);

  event RoleUnpaused(Role indexed role);

  enum Role {
    OPERATOR,
    RECOVERER,
    CANCELLER,
    DISABLER,
    PAUSER
  }

  struct RoleStatus {
    address account;
    bool paused;
  }

  function cancelAccountRecovery(
    address smartWallet, address newUserSigningKey
  ) external;

  function cancelAccountRecoveryDisablement(address smartWallet) external;

  function setRole(Role role, address account) external;

  function removeRole(Role role) external;

  function pause(Role role) external;

  function unpause(Role role) external;

  function isPaused(Role role) external view returns (bool paused);

  function isRole(Role role) external view returns (bool hasRole);

  function getOperator() external view returns (address operator);

  function getRecoverer() external view returns (address recoverer);

  function getCanceller() external view returns (address canceller);

  function getDisabler() external view returns (address disabler);

  function getPauser() external view returns (address pauser);
}


interface TimelockerInterface {
  // Fire an event any time a timelock is initiated.
  event TimelockInitiated(
    bytes4 functionSelector, // selector of the function
    uint256 timeComplete,    // timestamp at which the function can be called
    bytes arguments,         // abi-encoded function arguments to call with
    uint256 timeExpired      // timestamp where function can no longer be called
  );

  // Fire an event any time a minimum timelock interval is modified.
  event TimelockIntervalModified(
    bytes4 functionSelector, // selector of the function
    uint256 oldInterval,     // old minimum timelock interval for the function
    uint256 newInterval      // new minimum timelock interval for the function
  );

  // Fire an event any time a default timelock expiration is modified.
  event TimelockExpirationModified(
    bytes4 functionSelector, // selector of the function
    uint256 oldExpiration,   // old default timelock expiration for the function
    uint256 newExpiration    // new default timelock expiration for the function
  );

  // Each timelock has timestamps for when it is complete and when it expires.
  struct Timelock {
    uint128 complete;
    uint128 expires;
  }

  // Functions have a timelock interval and time from completion to expiration.
  struct TimelockDefaults {
    uint128 interval;
    uint128 expiration;
  }

  function getTimelock(
    bytes4 functionSelector, bytes calldata arguments
  ) external view returns (
    bool exists,
    bool completed,
    bool expired,
    uint256 completionTime,
    uint256 expirationTime
  );

  function getDefaultTimelockInterval(
    bytes4 functionSelector
  ) external view returns (uint256 defaultTimelockInterval);

  function getDefaultTimelockExpiration(
    bytes4 functionSelector
  ) external view returns (uint256 defaultTimelockExpiration);
}


interface TimelockerModifiersInterface {
  function initiateModifyTimelockInterval(
    bytes4 functionSelector, uint256 newTimelockInterval, uint256 extraTime
  ) external;

  function modifyTimelockInterval(
    bytes4 functionSelector, uint256 newTimelockInterval
  ) external;

  function initiateModifyTimelockExpiration(
    bytes4 functionSelector, uint256 newTimelockExpiration, uint256 extraTime
  ) external;

  function modifyTimelockExpiration(
    bytes4 functionSelector, uint256 newTimelockExpiration
  ) external;
}


interface DharmaSmartWalletRecoveryInterface {
  function recover(address newUserSigningKey) external;
  function getUserSigningKey() external view returns (address userSigningKey);
}


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

    return c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a, "SafeMath: subtraction overflow");
    uint256 c = a - b;

    return c;
  }

  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }

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

    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b > 0, "SafeMath: division by zero");
    uint256 c = a / b;

    return c;
  }

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


/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be aplied to your functions to restrict their use to
 * the owner.
 *
 * In order to transfer ownership, a recipient must be specified, at which point
 * the specified recipient can call `acceptOwnership` and take ownership.
 */
contract TwoStepOwnable {
  address private _owner;

  address private _newPotentialOwner;

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

  /**
   * @dev Initialize contract by setting transaction submitter as initial owner.
   */
  constructor() internal {
    _owner = tx.origin;
    emit OwnershipTransferred(address(0), _owner);
  }

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

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

  /**
   * @dev Returns true if the caller is the current owner.
   */
  function isOwner() public view returns (bool) {
    return msg.sender == _owner;
  }

  /**
   * @dev Allows a new account (`newOwner`) to accept ownership.
   * Can only be called by the current owner.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    require(
      newOwner != address(0),
      "TwoStepOwnable: new potential owner is the zero address."
    );

    _newPotentialOwner = newOwner;
  }

  /**
   * @dev Cancel a transfer of ownership to a new account.
   * Can only be called by the current owner.
   */
  function cancelOwnershipTransfer() public onlyOwner {
    delete _newPotentialOwner;
  }

  /**
   * @dev Transfers ownership of the contract to the caller.
   * Can only be called by a new potential owner set by the current owner.
   */
  function acceptOwnership() public {
    require(
      msg.sender == _newPotentialOwner,
      "TwoStepOwnable: current owner must set caller as new potential owner."
    );

    delete _newPotentialOwner;

    emit OwnershipTransferred(_owner, msg.sender);

    _owner = msg.sender;
  }
}


/**
 * @title TimelockerV2
 * @author 0age
 * @notice This contract allows contracts that inherit it to implement timelocks
 * on functions, where the `_setTimelock` internal function must first be called
 * and passed the target function selector and arguments. Then, a given time
 * interval must first fully transpire before the timelock functions can be
 * successfully called. Furthermore, once a timelock is complete, it will expire
 * after a period of time. In order to change timelock intervals or expirations,
 * the inheriting contract needs to implement `modifyTimelockInterval` and
 * `modifyTimelockExpiration` functions, respectively, as well as functions that
 * call `_setTimelock` in order to initiate the timelocks for those functions.
 * To make a function timelocked, use the `_enforceTimelock` internal function.
 * To set initial defult minimum timelock intervals and expirations, use the
 * `_setInitialTimelockInterval` and `_setInitialTimelockExpiration` internal
 * functions - they can only be used during contract creation. Additionally,
 * there are three external getters (and internal equivalents): `getTimelock`,
 * `getDefaultTimelockInterval`, and `getDefaultTimelockExpiration`. Finally,
 * version two of the timelocker builds on version one by including an internal
 * `_expireTimelock` function for expiring an existing timelock, which can then
 * be reactivated as long as the completion time does not become shorter than
 * the original completion time.
 */
contract TimelockerV2 is TimelockerInterface {
  using SafeMath for uint256;

  // Implement a timelock for each function and set of arguments.
  mapping(bytes4 => mapping(bytes32 => Timelock)) private _timelocks;

  // Implement default timelock intervals and expirations for each function.
  mapping(bytes4 => TimelockDefaults) private _timelockDefaults;

  // Only allow one new interval or expiration change at a time per function.
  mapping(bytes4 => mapping(bytes4 => bytes32)) private _protectedTimelockIDs;

  // Store modifyTimelockInterval function selector as a constant.
  bytes4 private constant _MODIFY_TIMELOCK_INTERVAL_SELECTOR = bytes4(
    0xe950c085
  );

  // Store modifyTimelockExpiration function selector as a constant.
  bytes4 private constant _MODIFY_TIMELOCK_EXPIRATION_SELECTOR = bytes4(
    0xd7ce3c6f
  );

  // Set a ridiculously high duration in order to protect against overflows.
  uint256 private constant _A_TRILLION_YEARS = 365000000000000 days;

  /**
   * @notice In the constructor, confirm that selectors specified as constants
   * are correct.
   */
  constructor() internal {
    TimelockerModifiersInterface modifiers;

    bytes4 targetModifyInterval = modifiers.modifyTimelockInterval.selector;
    require(
      _MODIFY_TIMELOCK_INTERVAL_SELECTOR == targetModifyInterval,
      "Incorrect modify timelock interval selector supplied."
    );

    bytes4 targetModifyExpiration = modifiers.modifyTimelockExpiration.selector;
    require(
      _MODIFY_TIMELOCK_EXPIRATION_SELECTOR == targetModifyExpiration,
      "Incorrect modify timelock expiration selector supplied."
    );
  }

  /**
   * @notice View function to check if a timelock for the specified function and
   * arguments has completed.
   * @param functionSelector Function to be called.
   * @param arguments The abi-encoded arguments of the function to be called.
   * @return A boolean indicating if the timelock exists or not and the time at
   * which the timelock completes if it does exist.
   */
  function getTimelock(
    bytes4 functionSelector, bytes memory arguments
  ) public view returns (
    bool exists,
    bool completed,
    bool expired,
    uint256 completionTime,
    uint256 expirationTime
  ) {
    // Get information on the current timelock, if one exists.
    (exists, completed, expired, completionTime, expirationTime) = _getTimelock(
      functionSelector, arguments
    );
  }

  /**
   * @notice View function to check the current minimum timelock interval on a
   * given function.
   * @param functionSelector Function to retrieve the timelock interval for.
   * @return The current minimum timelock interval for the given function.
   */
  function getDefaultTimelockInterval(
    bytes4 functionSelector
  ) public view returns (uint256 defaultTimelockInterval) {
    defaultTimelockInterval = _getDefaultTimelockInterval(functionSelector);
  }

  /**
   * @notice View function to check the current default timelock expiration on a
   * given function.
   * @param functionSelector Function to retrieve the timelock expiration for.
   * @return The current default timelock expiration for the given function.
   */
  function getDefaultTimelockExpiration(
    bytes4 functionSelector
  ) public view returns (uint256 defaultTimelockExpiration) {
    defaultTimelockExpiration = _getDefaultTimelockExpiration(functionSelector);
  }

  /**
   * @notice Internal function that sets a timelock so that the specified
   * function can be called with the specified arguments. Note that existing
   * timelocks may be extended, but not shortened - this can also be used as a
   * method for "cancelling" a function call by extending the timelock to an
   * arbitrarily long duration. Keep in mind that new timelocks may be created
   * with a shorter duration on functions that already have other timelocks on
   * them, but only if they have different arguments.
   * @param functionSelector Selector of the function to be called.
   * @param arguments The abi-encoded arguments of the function to be called.
   * @param extraTime Additional time in seconds to add to the minimum timelock
   * interval for the given function.
   */
  function _setTimelock(
    bytes4 functionSelector, bytes memory arguments, uint256 extraTime
  ) internal {
    // Ensure that the specified extra time will not cause an overflow error.
    require(extraTime < _A_TRILLION_YEARS, "Supplied extra time is too large.");

    // Get timelock ID using the supplied function arguments.
    bytes32 timelockID = keccak256(abi.encodePacked(arguments));

    // For timelock interval or expiration changes, first drop any existing
    // timelock for the function being modified if the argument has changed.
    if (
      functionSelector == _MODIFY_TIMELOCK_INTERVAL_SELECTOR ||
      functionSelector == _MODIFY_TIMELOCK_EXPIRATION_SELECTOR
    ) {
      // Determine the function that will be modified by the timelock.
      (bytes4 modifiedFunction, uint256 duration) = abi.decode(
        arguments, (bytes4, uint256)
      );

      // Ensure that the new timelock duration will not cause an overflow error.
      require(
        duration < _A_TRILLION_YEARS,
        "Supplied default timelock duration to modify is too large."
      );

      // Determine the current timelockID, if any, for the modified function.
      bytes32 currentTimelockID = (
        _protectedTimelockIDs[functionSelector][modifiedFunction]
      );

      // Determine if current timelockID differs from what is currently set.
      if (currentTimelockID != timelockID) {
        // Drop existing timelock if one exists and has a different timelockID.
        if (currentTimelockID != bytes32(0)) {
          delete _timelocks[functionSelector][currentTimelockID];
        }

        // Register the new timelockID as the current protected timelockID.
        _protectedTimelockIDs[functionSelector][modifiedFunction] = timelockID;
      }
    }

    // Get timelock using current time, inverval for timelock ID, & extra time.
    uint256 timelock = uint256(
      _timelockDefaults[functionSelector].interval
    ).add(now).add(extraTime);

    // Get expiration time using timelock duration plus default expiration time.
    uint256 expiration = timelock.add(
      uint256(_timelockDefaults[functionSelector].expiration)
    );

    // Get the current timelock, if one exists.
    Timelock storage timelockStorage = _timelocks[functionSelector][timelockID];

    // Determine the duration of the current timelock.
    uint256 currentTimelock = uint256(timelockStorage.complete);

    // Ensure that the timelock duration does not decrease. Note that a new,
    // shorter timelock may still be set up on the same function in the event
    // that it is provided with different arguments. Also note that this can be
    // circumvented when modifying intervals or expirations by setting a new
    // timelock (removing the old one), then resetting the original timelock but
    // with a shorter duration.
    require(
      currentTimelock == 0 || timelock > currentTimelock,
      "Existing timelocks may only be extended."
    );

    // Set timelock completion and expiration using timelock ID and extra time.
    timelockStorage.complete = uint128(timelock);
    timelockStorage.expires = uint128(expiration);

    // Emit an event with all of the relevant information.
    emit TimelockInitiated(functionSelector, timelock, arguments, expiration);
  }

  /**
   * @notice Internal function for setting a new timelock interval for a given
   * function selector. The default for this function may also be modified, but
   * excessive values will cause the `modifyTimelockInterval` function to become
   * unusable.
   * @param functionSelector The selector of the function to set the timelock
   * interval for.
   * @param newTimelockInterval the new minimum timelock interval to set for the
   * given function.
   */
  function _modifyTimelockInterval(
    bytes4 functionSelector, uint256 newTimelockInterval
  ) internal {
    // Ensure that the timelock has been set and is completed.
    _enforceTimelockPrivate(
      _MODIFY_TIMELOCK_INTERVAL_SELECTOR,
      abi.encode(functionSelector, newTimelockInterval)
    );

    // Clear out the existing timelockID protection for the given function.
    delete _protectedTimelockIDs[
      _MODIFY_TIMELOCK_INTERVAL_SELECTOR
    ][functionSelector];

    // Set new timelock interval and emit a `TimelockIntervalModified` event.
    _setTimelockIntervalPrivate(functionSelector, newTimelockInterval);
  }

  /**
   * @notice Internal function for setting a new timelock expiration for a given
   * function selector. Once the minimum interval has elapsed, the timelock will
   * expire once the specified expiration time has elapsed. Setting this value
   * too low will result in timelocks that are very difficult to execute
   * correctly. Be sure to override the public version of this function with
   * appropriate access controls.
   * @param functionSelector The selector of the function to set the timelock
   * expiration for.
   * @param newTimelockExpiration The new minimum timelock expiration to set for
   * the given function.
   */
  function _modifyTimelockExpiration(
    bytes4 functionSelector, uint256 newTimelockExpiration
  ) internal {
    // Ensure that the timelock has been set and is completed.
    _enforceTimelockPrivate(
      _MODIFY_TIMELOCK_EXPIRATION_SELECTOR,
      abi.encode(functionSelector, newTimelockExpiration)
    );

    // Clear out the existing timelockID protection for the given function.
    delete _protectedTimelockIDs[
      _MODIFY_TIMELOCK_EXPIRATION_SELECTOR
    ][functionSelector];

    // Set new default expiration and emit a `TimelockExpirationModified` event.
    _setTimelockExpirationPrivate(functionSelector, newTimelockExpiration);
  }

  /**
   * @notice Internal function to set an initial timelock interval for a given
   * function selector. Only callable during contract creation.
   * @param functionSelector The selector of the function to set the timelock
   * interval for.
   * @param newTimelockInterval The new minimum timelock interval to set for the
   * given function.
   */
  function _setInitialTimelockInterval(
    bytes4 functionSelector, uint256 newTimelockInterval
  ) internal {
    // Ensure that this function is only callable during contract construction.
    assembly { if extcodesize(address) { revert(0, 0) } }

    // Set the timelock interval and emit a `TimelockIntervalModified` event.
    _setTimelockIntervalPrivate(functionSelector, newTimelockInterval);
  }

  /**
   * @notice Internal function to set an initial timelock expiration for a given
   * function selector. Only callable during contract creation.
   * @param functionSelector The selector of the function to set the timelock
   * expiration for.
   * @param newTimelockExpiration The new minimum timelock expiration to set for
   * the given function.
   */
  function _setInitialTimelockExpiration(
    bytes4 functionSelector, uint256 newTimelockExpiration
  ) internal {
    // Ensure that this function is only callable during contract construction.
    assembly { if extcodesize(address) { revert(0, 0) } }

    // Set the timelock interval and emit a `TimelockExpirationModified` event.
    _setTimelockExpirationPrivate(functionSelector, newTimelockExpiration);
  }

  /**
   * @notice Internal function to expire or cancel a timelock so it is no longer
   * usable. Once it has been expired, the timelock in question will only be
   * reactivated if the timelock is reset, and this operation is only permitted
   * if the completion time is not shorter than the original completion time.
   * @param functionSelector The function that the timelock to expire is set on.
   * @param arguments The abi-encoded arguments of the timelocked function call
   * to be expired.
   */
  function _expireTimelock(
    bytes4 functionSelector, bytes memory arguments
  ) internal {
    // Get timelock ID using the supplied function arguments.
    bytes32 timelockID = keccak256(abi.encodePacked(arguments));

    // Get the current timelock, if one exists.
    Timelock storage timelock = _timelocks[functionSelector][timelockID];

    uint256 currentTimelock = uint256(timelock.complete);
    uint256 expiration = uint256(timelock.expires);

    // Ensure a timelock is currently set for the given function and arguments.
    require(currentTimelock != 0, "No timelock found for the given arguments.");

    // Ensure that the timelock has not already expired.
    require(expiration > now, "Timelock has already expired.");

    // Mark the timelock as expired.
    timelock.expires = uint128(0);
  }

  /**
   * @notice Internal function to ensure that a timelock is complete or expired
   * and to clear the existing timelock if it is complete so it cannot later be
   * reused. The function to enforce the timelock on is inferred from `msg.sig`.
   * @param arguments The abi-encoded arguments of the function to be called.
   */
  function _enforceTimelock(bytes memory arguments) internal {
    // Enforce the relevant timelock.
    _enforceTimelockPrivate(msg.sig, arguments);
  }

  /**
   * @notice Internal view function to check if a timelock for the specified
   * function and arguments has completed.
   * @param functionSelector Function to be called.
   * @param arguments The abi-encoded arguments of the function to be called.
   * @return A boolean indicating if the timelock exists or not and the time at
   * which the timelock completes if it does exist.
   */
  function _getTimelock(
    bytes4 functionSelector, bytes memory arguments
  ) internal view returns (
    bool exists,
    bool completed,
    bool expired,
    uint256 completionTime,
    uint256 expirationTime
  ) {
    // Get timelock ID using the supplied function arguments.
    bytes32 timelockID = keccak256(abi.encodePacked(arguments));

    // Get information on the current timelock, if one exists.
    completionTime = uint256(_timelocks[functionSelector][timelockID].complete);
    exists = completionTime != 0;
    expirationTime = uint256(_timelocks[functionSelector][timelockID].expires);
    completed = exists && now > completionTime;
    expired = exists && now > expirationTime;
  }

  /**
   * @notice Internal view function to check the current minimum timelock
   * interval on a given function.
   * @param functionSelector Function to retrieve the timelock interval for.
   * @return The current minimum timelock interval for the given function.
   */
  function _getDefaultTimelockInterval(
    bytes4 functionSelector
  ) internal view returns (uint256 defaultTimelockInterval) {
    defaultTimelockInterval = uint256(
      _timelockDefaults[functionSelector].interval
    );
  }

  /**
   * @notice Internal view function to check the current default timelock
   * expiration on a given function.
   * @param functionSelector Function to retrieve the timelock expiration for.
   * @return The current default timelock expiration for the given function.
   */
  function _getDefaultTimelockExpiration(
    bytes4 functionSelector
  ) internal view returns (uint256 defaultTimelockExpiration) {
    defaultTimelockExpiration = uint256(
      _timelockDefaults[functionSelector].expiration
    );
  }

  /**
   * @notice Private function to ensure that a timelock is complete or expired
   * and to clear the existing timelock if it is complete so it cannot later be
   * reused.
   * @param functionSelector Function to be called.
   * @param arguments The abi-encoded arguments of the function to be called.
   */
  function _enforceTimelockPrivate(
    bytes4 functionSelector, bytes memory arguments
  ) private {
    // Get timelock ID using the supplied function arguments.
    bytes32 timelockID = keccak256(abi.encodePacked(arguments));

    // Get the current timelock, if one exists.
    Timelock memory timelock = _timelocks[functionSelector][timelockID];

    uint256 currentTimelock = uint256(timelock.complete);
    uint256 expiration = uint256(timelock.expires);

    // Ensure that the timelock is set and has completed.
    require(
      currentTimelock != 0 && currentTimelock <= now, "Timelock is incomplete."
    );

    // Ensure that the timelock has not expired.
    require(expiration > now, "Timelock has expired.");

    // Clear out the existing timelock so that it cannot be reused.
    delete _timelocks[functionSelector][timelockID];
  }

  /**
   * @notice Private function for setting a new timelock interval for a given
   * function selector.
   * @param functionSelector the selector of the function to set the timelock
   * interval for.
   * @param newTimelockInterval the new minimum timelock interval to set for the
   * given function.
   */
  function _setTimelockIntervalPrivate(
    bytes4 functionSelector, uint256 newTimelockInterval
  ) private {
    // Ensure that the new timelock interval will not cause an overflow error.
    require(
      newTimelockInterval < _A_TRILLION_YEARS,
      "Supplied minimum timelock interval is too large."
    );

    // Get the existing timelock interval, if any.
    uint256 oldTimelockInterval = uint256(
      _timelockDefaults[functionSelector].interval
    );

    // Update the timelock interval on the provided function.
    _timelockDefaults[functionSelector].interval = uint128(newTimelockInterval);

    // Emit a `TimelockIntervalModified` event with the appropriate arguments.
    emit TimelockIntervalModified(
      functionSelector, oldTimelockInterval, newTimelockInterval
    );
  }

  /**
   * @notice Private function for setting a new timelock expiration for a given
   * function selector.
   * @param functionSelector the selector of the function to set the timelock
   * interval for.
   * @param newTimelockExpiration the new default timelock expiration to set for
   * the given function.
   */
  function _setTimelockExpirationPrivate(
    bytes4 functionSelector, uint256 newTimelockExpiration
  ) private {
    // Ensure that the new timelock expiration will not cause an overflow error.
    require(
      newTimelockExpiration < _A_TRILLION_YEARS,
      "Supplied default timelock expiration is too large."
    );

    // Ensure that the new timelock expiration is not too short.
    require(
      newTimelockExpiration > 1 minutes,
      "New timelock expiration is too short."
    );

    // Get the existing timelock expiration, if any.
    uint256 oldTimelockExpiration = uint256(
      _timelockDefaults[functionSelector].expiration
    );

    // Update the timelock expiration on the provided function.
    _timelockDefaults[functionSelector].expiration = uint128(
      newTimelockExpiration
    );

    // Emit a `TimelockExpirationModified` event with the appropriate arguments.
    emit TimelockExpirationModified(
      functionSelector, oldTimelockExpiration, newTimelockExpiration
    );
  }
}


/**
 * @title DharmaAccountRecoveryManagerV2
 * @author 0age
 * @notice This contract is owned by an Account Recovery multisig and manages
 * resets to user signing keys when necessary. It implements a set of timelocked
 * functions, where the `setTimelock` function must first be called, with the
 * same arguments that the function will be supplied with. Then, a given time
 * interval must first fully transpire before the timelock functions can be
 * successfully called.
 *
 * The timelocked functions currently implemented include:
 *  recover(address wallet, address newUserSigningKey)
 *  disableAccountRecovery(address wallet)
 *  modifyTimelockInterval(bytes4 functionSelector, uint256 newTimelockInterval)
 *  modifyTimelockExpiration(
 *    bytes4 functionSelector, uint256 newTimelockExpiration
 *  )
 *
 * Note that special care should be taken to differentiate between lost keys and
 * compromised keys, and that the danger of a user being impersonated is
 * extremely high. Account recovery should progress to a system where the user
 * builds their preferred account recovery procedure into a "key ring" smart
 * contract at their signing address, reserving this "hard reset" for extremely
 * unusual circumstances and eventually sunsetting it entirely.
 *
 * V2 of the Account Recovery Manager builds on V1 by introducing the concept of
 * "roles" - these are dedicated accounts that can be modified by the owner, and
 * that can trigger specific functionality on the manager. These roles are:
 *  - operator: initiates timelocks for account recovery + disablement
 *  - recoverer: triggers account recovery once timelock is complete
 *  - disabler: triggers account recovery disablement once timelock is complete
 *  - canceller: cancels account recovery and recovery disablement timelocks
 *  - pauser: pauses any role (where only the owner is then able to unpause it)
 *
 * V2 also provides dedicated methods for cancelling timelocks related to
 * account recovery or the disablement of account recovery, as well as functions
 * for managing, pausing, and querying for the status of the various roles.
 */
contract DharmaAccountRecoveryManagerV2 is
  DharmaAccountRecoveryManagerInterface,
  DharmaAccountRecoveryManagerV2Interface,
  TimelockerModifiersInterface,
  TwoStepOwnable,
  TimelockerV2 {
  using SafeMath for uint256;

  // Maintain a role status mapping with assigned accounts and paused states.
  mapping(uint256 => RoleStatus) private _roles;

  // Maintain mapping of smart wallets that have opted out of account recovery.
  mapping(address => bool) private _accountRecoveryDisabled;

  /**
   * @notice In the constructor, set the initial owner to the transaction
   * submitter and initial minimum timelock interval and default timelock
   * expiration values.
   */
  constructor() public {
    // Set initial minimum timelock interval values.
    _setInitialTimelockInterval(this.modifyTimelockInterval.selector, 2 weeks);
    _setInitialTimelockInterval(
      this.modifyTimelockExpiration.selector, 2 weeks
    );
    _setInitialTimelockInterval(this.recover.selector, 3 days);
    _setInitialTimelockInterval(this.disableAccountRecovery.selector, 3 days);

    // Set initial default timelock expiration values.
    _setInitialTimelockExpiration(this.modifyTimelockInterval.selector, 7 days);
    _setInitialTimelockExpiration(
      this.modifyTimelockExpiration.selector, 7 days
    );
    _setInitialTimelockExpiration(this.recover.selector, 3 days);
    _setInitialTimelockExpiration(this.disableAccountRecovery.selector, 3 days);
  }

  /**
   * @notice Initiates a timelocked account recovery process for a smart wallet
   * user signing key. Only the owner or the designated operator may call this
   * function. Once the timelock period is complete (and before it has expired)
   * the owner or the designated recoverer may call `recover` to complete the
   * process and reset the user's signing key.
   * @param smartWallet The smart wallet address.
   * @param userSigningKey The new user signing key.
   * @param extraTime Additional time in seconds to add to the timelock.
   */
  function initiateAccountRecovery(
    address smartWallet, address userSigningKey, uint256 extraTime
  ) external onlyOwnerOr(Role.OPERATOR) {
    require(smartWallet != address(0), "No smart wallet address provided.");
    require(userSigningKey != address(0), "No new user signing key provided.");

    // Set the timelock and emit a `TimelockInitiated` event.
    _setTimelock(
      this.recover.selector, abi.encode(smartWallet, userSigningKey), extraTime
    );
  }

  /**
   * @notice Timelocked function to set a new user signing key on a smart
   * wallet. Only the owner or the designated recoverer may call this function.
   * @param smartWallet Address of the smart wallet to recover a key on.
   * @param newUserSigningKey Address of the new signing key for the user.
   */
  function recover(
    address smartWallet, address newUserSigningKey
  ) external onlyOwnerOr(Role.RECOVERER) {
    require(smartWallet != address(0), "No smart wallet address provided.");
    require(
      newUserSigningKey != address(0),
      "No new user signing key provided."
    );

    // Ensure that the wallet in question has not opted out of account recovery.
    require(
      !_accountRecoveryDisabled[smartWallet],
      "This wallet has elected to opt out of account recovery functionality."
    );

    // Ensure that the timelock has been set and is completed.
    _enforceTimelock(abi.encode(smartWallet, newUserSigningKey));

    // Declare the proper interface for the smart wallet in question.
    DharmaSmartWalletRecoveryInterface walletInterface;

    // Attempt to get current signing key - a failure should not block recovery.
    address oldUserSigningKey;
    (bool ok, bytes memory data) = smartWallet.call.gas(gasleft() / 2)(
      abi.encodeWithSelector(walletInterface.getUserSigningKey.selector)
    );
    if (ok && data.length == 32) {
      oldUserSigningKey = abi.decode(data, (address));
    }

    // Call the specified smart wallet and supply the new user signing key.
    DharmaSmartWalletRecoveryInterface(smartWallet).recover(newUserSigningKey);

    // Emit an event to signify that the wallet in question was recovered.
    emit Recovery(smartWallet, oldUserSigningKey, newUserSigningKey);
  }

  /**
   * @notice Initiates a timelocked account recovery disablement process for a
   * smart wallet. Only the owner or the designated operator may call this
   * function. Once the timelock period is complete (and before it has expired)
   * the owner or the designated disabler may call `disableAccountRecovery` to
   * complete the process and opt a smart wallet out of account recovery. Once
   * account recovery has been disabled, it cannot be reenabled - the process is
   * irreversible.
   * @param smartWallet The smart wallet address.
   * @param extraTime Additional time in seconds to add to the timelock.
   */
  function initiateAccountRecoveryDisablement(
    address smartWallet, uint256 extraTime
  ) external onlyOwnerOr(Role.OPERATOR) {
    require(smartWallet != address(0), "No smart wallet address provided.");

    // Set the timelock and emit a `TimelockInitiated` event.
    _setTimelock(
      this.disableAccountRecovery.selector, abi.encode(smartWallet), extraTime
    );
  }

  /**
   * @notice Timelocked function to opt a given wallet out of account recovery.
   * This action cannot be undone - any future account recovery would require an
   * upgrade to the smart wallet implementation itself and is not likely to be
   * supported. Only the owner or the designated disabler may call this
   * function.
   * @param smartWallet Address of the smart wallet to disable account recovery
   * for.
   */
  function disableAccountRecovery(
    address smartWallet
  ) external onlyOwnerOr(Role.DISABLER) {
    require(smartWallet != address(0), "No smart wallet address provided.");

    // Ensure that the timelock has been set and is completed.
    _enforceTimelock(abi.encode(smartWallet));

    // Register the specified wallet as having opted out of account recovery.
    _accountRecoveryDisabled[smartWallet] = true;

    // Emit an event to signify the wallet in question is no longer recoverable.
    emit RecoveryDisabled(smartWallet);
  }

  /**
   * @notice Cancel a pending timelock for setting a new user signing key on a
   * smart wallet. Only the owner or the designated canceller may call this
   * function.
   * @param smartWallet Address of the smart wallet to cancel the recovery on.
   * @param userSigningKey Address of the signing key supplied for the user.
   */
  function cancelAccountRecovery(
    address smartWallet, address userSigningKey
  ) external onlyOwnerOr(Role.CANCELLER) {
    require(smartWallet != address(0), "No smart wallet address provided.");
    require(userSigningKey != address(0), "No user signing key provided.");

    // Expire the timelock for the account recovery in question if one exists.
    _expireTimelock(
      this.recover.selector, abi.encode(smartWallet, userSigningKey)
    );

    // Emit an event to signify that the recovery was cancelled.
    emit RecoveryCancelled(smartWallet, userSigningKey);
  }

  /**
   * @notice Cancel a pending timelock for disabling account recovery for a
   * smart wallet. Only the owner or the designated canceller may call this
   * function.
   * @param smartWallet Address of the smart wallet to cancel the recovery
   * disablement on.
   */
  function cancelAccountRecoveryDisablement(
    address smartWallet
  ) external onlyOwnerOr(Role.CANCELLER) {
    require(smartWallet != address(0), "No smart wallet address provided.");

    // Expire account recovery disablement timelock in question if one exists.
    _expireTimelock(
      this.disableAccountRecovery.selector, abi.encode(smartWallet)
    );

    // Emit an event to signify that the recovery disablement was cancelled.
    emit RecoveryDisablementCancelled(smartWallet);
  }

  /**
   * @notice Pause a currently unpaused role and emit a `RolePaused` event. Only
   * the owner or the designated pauser may call this function. Also, bear in
   * mind that only the owner may unpause a role once paused.
   * @param role The role to pause. Permitted roles are operator (0),
   * recoverer (1), canceller (2), disabler (3), and pauser (4).
   */
  function pause(Role role) external onlyOwnerOr(Role.PAUSER) {
    RoleStatus storage storedRoleStatus = _roles[uint256(role)];
    require(!storedRoleStatus.paused, "Role in question is already paused.");
    storedRoleStatus.paused = true;
    emit RolePaused(role);
  }

  /**
   * @notice Unause a currently paused role and emit a `RoleUnpaused` event.
   * Only the owner may call this function.
   * @param role The role to pause. Permitted roles are operator (0),
   * recoverer (1), canceller (2), disabler (3), and pauser (4).
   */
  function unpause(Role role) external onlyOwner {
    RoleStatus storage storedRoleStatus = _roles[uint256(role)];
    require(storedRoleStatus.paused, "Role in question is already unpaused.");
    storedRoleStatus.paused = false;
    emit RoleUnpaused(role);
  }

  /**
   * @notice Sets the timelock for a new timelock interval for a given function
   * selector. Only the owner may call this function.
   * @param functionSelector The selector of the function to set the timelock
   * interval for.
   * @param newTimelockInterval The new timelock interval to set for the given
   * function selector.
   * @param extraTime Additional time in seconds to add to the timelock.
   */
  function initiateModifyTimelockInterval(
    bytes4 functionSelector, uint256 newTimelockInterval, uint256 extraTime
  ) external onlyOwner {
    // Ensure that a function selector is specified (no 0x00000000 selector).
    require(
      functionSelector != bytes4(0),
      "Function selector cannot be empty."
    );

    // Ensure a timelock interval over eight weeks is not set on this function.
    if (functionSelector == this.modifyTimelockInterval.selector) {
      require(
        newTimelockInterval <= 8 weeks,
        "Timelock interval of modifyTimelockInterval cannot exceed eight weeks."
      );
    }

    // Set the timelock and emit a `TimelockInitiated` event.
    _setTimelock(
      this.modifyTimelockInterval.selector,
      abi.encode(functionSelector, newTimelockInterval),
      extraTime
    );
  }

  /**
   * @notice Sets a new timelock interval for a given function selector. The
   * default for this function may also be modified, but has a maximum allowable
   * value of eight weeks. Only the owner may call this function.
   * @param functionSelector The selector of the function to set the timelock
   * interval for.
   * @param newTimelockInterval The new timelock interval to set for the given
   * function selector.
   */
  function modifyTimelockInterval(
    bytes4 functionSelector, uint256 newTimelockInterval
  ) external onlyOwner {
    // Ensure that a function selector is specified (no 0x00000000 selector).
    require(
      functionSelector != bytes4(0),
      "Function selector cannot be empty."
    );

    // Continue via logic in the inherited `_modifyTimelockInterval` function.
    _modifyTimelockInterval(functionSelector, newTimelockInterval);
  }

  /**
   * @notice Sets a new timelock expiration for a given function selector. The
   * default Only the owner may call this function. New expiration durations may
   * not exceed one month.
   * @param functionSelector The selector of the function to set the timelock
   * expiration for.
   * @param newTimelockExpiration The new timelock expiration to set for the
   * given function selector.
   * @param extraTime Additional time in seconds to add to the timelock.
   */
  function initiateModifyTimelockExpiration(
    bytes4 functionSelector, uint256 newTimelockExpiration, uint256 extraTime
  ) external onlyOwner {
    // Ensure that a function selector is specified (no 0x00000000 selector).
    require(
      functionSelector != bytes4(0),
      "Function selector cannot be empty."
    );

    // Ensure that the supplied default expiration does not exceed 1 month.
    require(
      newTimelockExpiration <= 30 days,
      "New timelock expiration cannot exceed one month."
    );

    // Ensure a timelock expiration under one hour is not set on this function.
    if (functionSelector == this.modifyTimelockExpiration.selector) {
      require(
        newTimelockExpiration >= 60 minutes,
        "Expiration of modifyTimelockExpiration must be at least an hour long."
      );
    }

    // Set the timelock and emit a `TimelockInitiated` event.
    _setTimelock(
      this.modifyTimelockExpiration.selector,
      abi.encode(functionSelector, newTimelockExpiration),
      extraTime
    );
  }

  /**
   * @notice Sets a new timelock expiration for a given function selector. The
   * default for this function may also be modified, but has a minimum allowable
   * value of one hour. Only the owner may call this function.
   * @param functionSelector The selector of the function to set the timelock
   * expiration for.
   * @param newTimelockExpiration The new timelock expiration to set for the
   * given function selector.
   */
  function modifyTimelockExpiration(
    bytes4 functionSelector, uint256 newTimelockExpiration
  ) external onlyOwner {
    // Ensure that a function selector is specified (no 0x00000000 selector).
    require(
      functionSelector != bytes4(0),
      "Function selector cannot be empty."
    );

    // Continue via logic in the inherited `_modifyTimelockExpiration` function.
    _modifyTimelockExpiration(
      functionSelector, newTimelockExpiration
    );
  }

  /**
   * @notice Set a new account on a given role and emit a `RoleModified` event
   * if the role holder has changed. Only the owner may call this function.
   * @param role The role that the account will be set for. Permitted roles are
   * operator (0), recoverer (1), canceller (2), disabler (3), and pauser (4).
   * @param account The account to set as the designated role bearer.
   */
  function setRole(Role role, address account) external onlyOwner {
    require(account != address(0), "Must supply an account.");
    _setRole(role, account);
  }

  /**
   * @notice Remove any current role bearer for a given role and emit a
   * `RoleModified` event if a role holder was previously set. Only the owner
   * may call this function.
   * @param role The role that the account will be removed from. Permitted roles
   * are operator (0), recoverer (1), canceller (2), disabler (3), and
   * pauser (4).
   */
  function removeRole(Role role) external onlyOwner {
    _setRole(role, address(0));
  }

  /**
   * @notice External view function to check whether a given smart wallet has
   * disabled account recovery by opting out.
   * @param smartWallet Address of the smart wallet to check.
   * @return A boolean indicating if account recovery has been disabled for the
   * wallet in question.
   */
  function accountRecoveryDisabled(
    address smartWallet
  ) external view returns (bool hasDisabledAccountRecovery) {
    // Determine if the wallet in question has opted out of account recovery.
    hasDisabledAccountRecovery = _accountRecoveryDisabled[smartWallet];
  }

  /**
   * @notice External view function to check whether or not the functionality
   * associated with a given role is currently paused or not. The owner or the
   * pauser may pause any given role (including the pauser itself), but only the
   * owner may unpause functionality. Additionally, the owner may call paused
   * functions directly.
   * @param role The role to check the pause status on. Permitted roles are
   * operator (0), recoverer (1), canceller (2), disabler (3), and pauser (4).
   * @return A boolean to indicate if the functionality associated with the role
   * in question is currently paused.
   */
  function isPaused(Role role) external view returns (bool paused) {
    paused = _isPaused(role);
  }

  /**
   * @notice External view function to check whether the caller is the current
   * role holder.
   * @param role The role to check for. Permitted roles are operator (0),
   * recoverer (1), canceller (2), disabler (3), and pauser (4).
   * @return A boolean indicating if the caller has the specified role.
   */
  function isRole(Role role) external view returns (bool hasRole) {
    hasRole = _isRole(role);
  }

  /**
   * @notice External view function to check the account currently holding the
   * operator role. The operator can initiate timelocks for account recovery and
   * account recovery disablement.
   * @return The address of the current operator, or the null address if none is
   * set.
   */
  function getOperator() external view returns (address operator) {
    operator = _roles[uint256(Role.OPERATOR)].account;
  }

  /**
   * @notice External view function to check the account currently holding the
   * recoverer role. The recoverer can trigger smart wallet account recovery in
   * the event that a timelock has been initiated and is complete and not yet
   * expired.
   * @return The address of the current recoverer, or the null address if none
   * is set.
   */
  function getRecoverer() external view returns (address recoverer) {
    recoverer = _roles[uint256(Role.RECOVERER)].account;
  }

  /**
   * @notice External view function to check the account currently holding the
   * canceller role. The canceller can expire a timelock related to account
   * recovery or account recovery disablement prior to its execution.
   * @return The address of the current canceller, or the null address if none
   * is set.
   */
  function getCanceller() external view returns (address canceller) {
    canceller = _roles[uint256(Role.CANCELLER)].account;
  }

  /**
   * @notice External view function to check the account currently holding the
   * disabler role. The disabler can trigger permanent smart wallet account
   * recovery disablement in the event that a timelock has been initiated and is
   * complete and not yet expired.
   * @return The address of the current disabler, or the null address if none is
   * set.
   */
  function getDisabler() external view returns (address disabler) {
    disabler = _roles[uint256(Role.DISABLER)].account;
  }

  /**
   * @notice External view function to check the account currently holding the
   * pauser role. The pauser can pause any role from taking its standard action,
   * though the owner will still be able to call the associated function in the
   * interim and is the only entity able to unpause the given role once paused.
   * @return The address of the current pauser, or the null address if none is
   * set.
   */
  function getPauser() external view returns (address pauser) {
    pauser = _roles[uint256(Role.PAUSER)].account;
  }

  /**
   * @notice Internal function to set a new account on a given role and emit a
   * `RoleModified` event if the role holder has changed.
   * @param role The role that the account will be set for. Permitted roles are
   * operator (0), recoverer (1), canceller (2), disabler (3), and pauser (4).
   * @param account The account to set as the designated role bearer.
   */
  function _setRole(Role role, address account) internal {
    RoleStatus storage storedRoleStatus = _roles[uint256(role)];

    if (account != storedRoleStatus.account) {
      storedRoleStatus.account = account;
      emit RoleModified(role, account);
    }
  }

  /**
   * @notice Internal view function to check whether the caller is the current
   * role holder.
   * @param role The role to check for. Permitted roles are operator (0),
   * recoverer (1), canceller (2), disabler (3), and pauser (4).
   * @return A boolean indicating if the caller has the specified role.
   */
  function _isRole(Role role) internal view returns (bool hasRole) {
    hasRole = msg.sender == _roles[uint256(role)].account;
  }

  /**
   * @notice Internal view function to check whether the given role is paused or
   * not.
   * @param role The role to check for. Permitted roles are operator (0),
   * recoverer (1), canceller (2), disabler (3), and pauser (4).
   * @return A boolean indicating if the specified role is paused or not.
   */
  function _isPaused(Role role) internal view returns (bool paused) {
    paused = _roles[uint256(role)].paused;
  }

  /**
   * @notice Modifier that throws if called by any account other than the owner
   * or the supplied role, or if the caller is not the owner and the role in
   * question is paused.
   * @param role The role to require unless the caller is the owner. Permitted
   * roles are operator (0), recoverer (1), canceller (2), disabler (3), and
   * pauser (4).
   */
  modifier onlyOwnerOr(Role role) {
    if (!isOwner()) {
      require(_isRole(role), "Caller does not have a required role.");
      require(!_isPaused(role), "Role in question is currently paused.");
    }
    _;
  }
}

Contract Security Audit

Contract ABI

[{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"},{"internalType":"address","name":"userSigningKey","type":"address"}],"name":"cancelAccountRecovery","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"}],"name":"disableAccountRecovery","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"cancelOwnershipTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"},{"internalType":"uint256","name":"extraTime","type":"uint256"}],"name":"initiateAccountRecoveryDisablement","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"}],"name":"getDefaultTimelockInterval","outputs":[{"internalType":"uint256","name":"defaultTimelockInterval","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"uint256","name":"newTimelockInterval","type":"uint256"},{"internalType":"uint256","name":"extraTime","type":"uint256"}],"name":"initiateModifyTimelockInterval","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"}],"name":"accountRecoveryDisabled","outputs":[{"internalType":"bool","name":"hasDisabledAccountRecovery","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"},{"internalType":"address","name":"newUserSigningKey","type":"address"}],"name":"recover","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"},{"internalType":"address","name":"userSigningKey","type":"address"},{"internalType":"uint256","name":"extraTime","type":"uint256"}],"name":"initiateAccountRecovery","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getPauser","outputs":[{"internalType":"address","name":"pauser","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getCanceller","outputs":[{"internalType":"address","name":"canceller","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"}],"name":"getDefaultTimelockExpiration","outputs":[{"internalType":"uint256","name":"defaultTimelockExpiration","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDisabler","outputs":[{"internalType":"address","name":"disabler","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"isRole","outputs":[{"internalType":"bool","name":"hasRole","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"isPaused","outputs":[{"internalType":"bool","name":"paused","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"uint256","name":"newTimelockExpiration","type":"uint256"}],"name":"modifyTimelockExpiration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"removeRole","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOperator","outputs":[{"internalType":"address","name":"operator","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"uint256","name":"newTimelockInterval","type":"uint256"}],"name":"modifyTimelockInterval","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"bytes","name":"arguments","type":"bytes"}],"name":"getTimelock","outputs":[{"internalType":"bool","name":"exists","type":"bool"},{"internalType":"bool","name":"completed","type":"bool"},{"internalType":"bool","name":"expired","type":"bool"},{"internalType":"uint256","name":"completionTime","type":"uint256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"},{"internalType":"address","name":"account","type":"address"}],"name":"setRole","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"}],"name":"cancelAccountRecoveryDisablement","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"uint256","name":"newTimelockExpiration","type":"uint256"},{"internalType":"uint256","name":"extraTime","type":"uint256"}],"name":"initiateModifyTimelockExpiration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getRecoverer","outputs":[{"internalType":"address","name":"recoverer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"indexed":false,"internalType":"uint256","name":"timeComplete","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"arguments","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"timeExpired","type":"uint256"}],"name":"TimelockInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"indexed":false,"internalType":"uint256","name":"oldInterval","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newInterval","type":"uint256"}],"name":"TimelockIntervalModified","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"indexed":false,"internalType":"uint256","name":"oldExpiration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newExpiration","type":"uint256"}],"name":"TimelockExpirationModified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"address","name":"cancelledUserSigningKey","type":"address"}],"name":"RecoveryCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"}],"name":"RecoveryDisablementCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"RoleModified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"RolePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum DharmaAccountRecoveryManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"RoleUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"address","name":"oldUserSigningKey","type":"address"},{"indexed":false,"internalType":"address","name":"newUserSigningKey","type":"address"}],"name":"Recovery","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"}],"name":"RecoveryDisabled","type":"event"}]

60806040523480156200001157600080fd5b50600080546001600160a01b03191632178082556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36200008a7fe950c085000000000000000000000000000000000000000000000000000000006212750062000218565b620000c27fd7ce3c6f00000000000000000000000000000000000000000000000000000000621275006001600160e01b036200021816565b620000fa7f648bf774000000000000000000000000000000000000000000000000000000006203f4806001600160e01b036200021816565b620001327f1e225a6e000000000000000000000000000000000000000000000000000000006203f4806001600160e01b036200021816565b6200016a7fe950c0850000000000000000000000000000000000000000000000000000000062093a806001600160e01b036200023e16565b620001a27fd7ce3c6f0000000000000000000000000000000000000000000000000000000062093a806001600160e01b036200023e16565b620001da7f648bf774000000000000000000000000000000000000000000000000000000006203f4806001600160e01b036200023e16565b620002127f1e225a6e000000000000000000000000000000000000000000000000000000006203f4806001600160e01b036200023e16565b620004bf565b303b156200022557600080fd5b6200023a82826001600160e01b036200026016565b5050565b303b156200024b57600080fd5b6200023a82826001600160e01b036200035a16565b6801b5a660ea44b800008110620002c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806200300a6030913960400191505060405180910390fd5b7fffffffff00000000000000000000000000000000000000000000000000000000821660008181526003602090815260409182902080546001600160801b038681166001600160801b0319831617909255835194855216908301819052828201849052905190917f559d7dd60c597cca6d78f7577a0778cbe3d5fbd56636087e185037f260d83338919081900360600190a1505050565b6801b5a660ea44b800008110620003bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603281526020018062002fd86032913960400191505060405180910390fd5b603c811162000418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018062002fb36025913960400191505060405180910390fd5b7fffffffff00000000000000000000000000000000000000000000000000000000821660008181526003602090815260409182902080546001600160801b0386811670010000000000000000000000000000000090810282841617909355845195865291900416908301819052828201849052905190917f63f1567641b865eea56986985cc3702d7040232ddf6fde052234a17e97cc5889919081900360600190a1505050565b612ae480620004cf6000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639d003e0411610104578063e950c085116100a2578063f2fde38b11610071578063f2fde38b146105fb578063f5d3b65114610621578063f6e6761e14610647578063fd717de21461067a576101da565b8063e950c0851461049b578063ec2cd043146104c8578063edf07f15146105ac578063f2e12a39146105cc576101da565b8063bc61e733116100de578063bc61e73314610426578063d7ce3c6f14610446578063dab41d0d14610473578063e7f43c6814610493576101da565b80639d003e04146103d7578063afb24ecf146103fe578063bb60332014610406576101da565b806363e0cf4a1161017c57806379ba50971161014b57806379ba5097146103b75780638613959a146103bf5780638da5cb5b146103c75780638f32d59b146103cf576101da565b806363e0cf4a146102f5578063648bf7741461032f57806368a477fc1461035d5780637008b54814610393576101da565b806329904232116101b8578063299042321461023d578063301c7e5d14610269578063336e73d0146102895780635f679530146102c2576101da565b80630f664e6c146101df5780631e225a6e1461020f57806323452b9c14610235575b600080fd5b61020d600480360360408110156101f557600080fd5b506001600160a01b0381358116916020013516610682565b005b61020d6004803603602081101561022557600080fd5b50356001600160a01b031661083c565b61020d6109ae565b61020d6004803603604081101561025357600080fd5b506001600160a01b038135169060200135610a03565b61020d6004803603602081101561027f57600080fd5b503560ff16610b27565b6102b06004803603602081101561029f57600080fd5b50356001600160e01b031916610c1a565b60408051918252519081900360200190f35b61020d600480360360608110156102d857600080fd5b506001600160e01b03198135169060208101359060400135610c2b565b61031b6004803603602081101561030b57600080fd5b50356001600160a01b0316610d4d565b604080519115158252519081900360200190f35b61020d6004803603604081101561034557600080fd5b506001600160a01b0381358116916020013516610d6b565b61020d6004803603606081101561037357600080fd5b506001600160a01b038135811691602081013590911690604001356110e9565b61039b61124e565b604080516001600160a01b039092168252519081900360200190f35b61020d611275565b61039b61131a565b61039b611326565b61031b611335565b6102b0600480360360208110156103ed57600080fd5b50356001600160e01b031916611346565b61039b611351565b61031b6004803603602081101561041c57600080fd5b503560ff1661135d565b61031b6004803603602081101561043c57600080fd5b503560ff16611368565b61020d6004803603604081101561045c57600080fd5b506001600160e01b03198135169060200135611373565b61020d6004803603602081101561048957600080fd5b503560ff1661140a565b61039b61145b565b61020d600480360360408110156104b157600080fd5b506001600160e01b03198135169060200135611466565b61057f600480360360408110156104de57600080fd5b6001600160e01b0319823516919081019060408101602082013564010000000081111561050a57600080fd5b82018360208201111561051c57600080fd5b8035906020019184600183028401116401000000008311171561053e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506114f9945050505050565b60408051951515865293151560208601529115158484015260608401526080830152519081900360a00190f35b61020d600480360360208110156105c257600080fd5b503560ff1661151e565b61020d600480360360408110156105e257600080fd5b50803560ff1690602001356001600160a01b031661166d565b61020d6004803603602081101561061157600080fd5b50356001600160a01b0316611715565b61020d6004803603602081101561063757600080fd5b50356001600160a01b03166117bf565b61020d6004803603606081101561065d57600080fd5b506001600160e01b0319813516906020810135906040013561191d565b61039b611a80565b600261068c611335565b6107195761069981611a8c565b6106d45760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b6106dd81611ac0565b156107195760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b03831661075e5760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6001600160a01b0382166107b9576040805162461bcd60e51b815260206004820152601d60248201527f4e6f2075736572207369676e696e67206b65792070726f76696465642e000000604482015290519081900360640190fd5b604080516001600160a01b03808616602083015284168183015281518082038301815260609091019091526107f690631922fddd60e21b90611af3565b604080516001600160a01b0384811682529151918516917f8506b00cd2df941a18335b7afb79ee5c531dc5cce3972b1b7bdf0211f96d711b9181900360200190a2505050565b6003610846611335565b6108d35761085381611a8c565b61088e5760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61089781611ac0565b156108d35760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b0382166109185760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6109528260405160200180826001600160a01b03166001600160a01b03168152602001915050604051602081830303815290604052611c40565b6001600160a01b038216600081815260066020908152604091829020805460ff19166001179055815192835290517fa6a1c7e9940e618f418f7c47c543aea6144e61d3e65fe63fd64e0edef19d9ac69281900390910190a15050565b6109b6611335565b6109f15760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b600180546001600160a01b0319169055565b6000610a0d611335565b610a9a57610a1a81611a8c565b610a555760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b610a5e81611ac0565b15610a9a5760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b038316610adf5760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b610b22631e225a6e60e01b8460405160200180826001600160a01b03166001600160a01b0316815260200191505060405160208183030381529060405284611c56565b505050565b610b2f611335565b610b6a5760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b600060056000836004811115610b7c57fe5b815260208101919091526040016000208054909150600160a01b900460ff16610bd65760405162461bcd60e51b81526004018080602001828103825260258152602001806129db6025913960400191505060405180910390fd5b805460ff60a01b19168155816004811115610bed57fe5b6040517fd9ff16dcccc040d408ddf47191ae2d5313510993b245b3a7ccfb0258a4401d7890600090a25050565b6000610c2582612026565b92915050565b610c33611335565b610c6e5760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b03198316610cb45760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b6001600160e01b0319831663e950c08560e01b1415610d0f576249d400821115610d0f5760405162461bcd60e51b815260040180806020018281038252604681526020018061277a6046913960600191505060405180910390fd5b604080516001600160e01b0319851660208201528082018490528151808203830181526060909101909152610b229063e950c08560e01b9083611c56565b6001600160a01b031660009081526006602052604090205460ff1690565b6001610d75611335565b610e0257610d8281611a8c565b610dbd5760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b610dc681611ac0565b15610e025760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b038316610e475760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6001600160a01b038216610e8c5760405162461bcd60e51b81526004018080602001828103825260218152602001806129536021913960400191505060405180910390fd5b6001600160a01b03831660009081526006602052604090205460ff1615610ee45760405162461bcd60e51b81526004018080602001828103825260458152602001806128ac6045913960600191505060405180910390fd5b604080516001600160a01b0380861660208301528416818301528151808203830181526060909101909152610f1890611c40565b60008060006060866001600160a01b031660025a81610f3357fe5b60408051600481526024810182526020810180516001600160e01b031663081a078d60e41b17815291518151949093049390929182918083835b60208310610f8c5780518252601f199092019160209182019101610f6d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114610fef576040519150601f19603f3d011682016040523d82523d6000602084013e610ff4565b606091505b5091509150818015611007575080516020145b156110265780806020019051602081101561102157600080fd5b505192505b866001600160a01b0316630cd865ec876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b15801561107e57600080fd5b505af1158015611092573d6000803e3d6000fd5b5050604080516001600160a01b0387811682528a811660208301528251908c1694507f6c0468512076e943ed3d1c5aae1d6903c72162713d86aedd1381b3ac19e10cec93509081900390910190a250505050505050565b60006110f3611335565b6111805761110081611a8c565b61113b5760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61114481611ac0565b156111805760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b0384166111c55760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6001600160a01b03831661120a5760405162461bcd60e51b81526004018080602001828103825260218152602001806129536021913960400191505060405180910390fd5b604080516001600160a01b038087166020830152851681830152815180820383018152606090910190915261124890631922fddd60e21b9084611c56565b50505050565b600060058160045b81526020810191909152604001600020546001600160a01b0316919050565b6001546001600160a01b031633146112be5760405162461bcd60e51b81526004018080602001828103825260458152602001806128676045913960600191505060405180910390fd5b600180546001600160a01b03191690556000805460405133926001600160a01b03909216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03191633179055565b60006005816002611256565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b6000610c258261204b565b60006005816003611256565b6000610c2582611a8c565b6000610c2582611ac0565b61137b611335565b6113b65760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b031982166113fc5760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b6114068282612077565b5050565b611412611335565b61144d5760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6114588160006120f7565b50565b600060058180611256565b61146e611335565b6114a95760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b031982166114ef5760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b6114068282612196565b600080600080600061150b8787612216565b939b929a50909850965090945092505050565b6004611528611335565b6115b55761153581611a8c565b6115705760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61157981611ac0565b156115b55760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6000600560008460048111156115c757fe5b815260208101919091526040016000208054909150600160a01b900460ff16156116225760405162461bcd60e51b8152600401808060200182810382526023815260200180612a256023913960400191505060405180910390fd5b805460ff60a01b1916600160a01b17815582600481111561163f57fe5b6040517fad75709c5a2559beeed6c59693a5ea8701185d51947d3eef38713bb0fe5891e990600090a2505050565b611675611335565b6116b05760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160a01b03811661170b576040805162461bcd60e51b815260206004820152601760248201527f4d75737420737570706c7920616e206163636f756e742e000000000000000000604482015290519081900360640190fd5b61140682826120f7565b61171d611335565b6117585760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160a01b03811661179d5760405162461bcd60e51b8152600401808060200182810382526038815260200180612a786038913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60026117c9611335565b611856576117d681611a8c565b6118115760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61181a81611ac0565b156118565760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b03821661189b5760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6118dd631e225a6e60e01b8360405160200180826001600160a01b03166001600160a01b03168152602001915050604051602081830303815290604052611af3565b604080516001600160a01b038416815290517f170985b339d7db71b7658093224871db8b69f5728f1f0c45459af399728b54db9181900360200190a15050565b611925611335565b6119605760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b031983166119a65760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b62278d008211156119e85760405162461bcd60e51b8152600401808060200182810382526030815260200180612a486030913960400191505060405180910390fd5b6001600160e01b0319831663d7ce3c6f60e01b1415611a4257610e10821015611a425760405162461bcd60e51b81526004018080602001828103825260458152602001806129966045913960600191505060405180910390fd5b604080516001600160e01b0319851660208201528082018490528151808203830181526060909101909152610b229063d7ce3c6f60e01b9083611c56565b60006005816001611256565b600060056000836004811115611a9e57fe5b81526020810191909152604001600020546001600160a01b0316331492915050565b600060056000836004811115611ad257fe5b8152602081019190915260400160002054600160a01b900460ff1692915050565b6000816040516020018082805190602001908083835b60208310611b285780518252601f199092019160209182019101611b09565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835284528151918101919091206001600160e01b0319891660009081526002835284812082825290925292902080549295509350506001600160801b038082169250600160801b9091041681611bd85760405162461bcd60e51b815260040180806020018281038252602a815260200180612818602a913960400191505060405180910390fd5b428111611c2c576040805162461bcd60e51b815260206004820152601d60248201527f54696d656c6f636b2068617320616c726561647920657870697265642e000000604482015290519081900360640190fd5b505080546001600160801b03169055505050565b6114586000356001600160e01b031916826122f7565b6801b5a660ea44b800008110611c9d5760405162461bcd60e51b81526004018080602001828103825260218152602001806126e16021913960400191505060405180910390fd5b6000826040516020018082805190602001908083835b60208310611cd25780518252601f199092019160209182019101611cb3565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f19018352909352805192019190912093505063e950c08560e01b6001600160e01b03198716149150819050611d3e57506001600160e01b0319841663d7ce3c6f60e01b145b15611e3857600080848060200190516040811015611d5b57600080fd5b50805160209091015190925090506801b5a660ea44b800008110611db05760405162461bcd60e51b815260040180806020018281038252603a815260200180612919603a913960400191505060405180910390fd5b6001600160e01b0319808716600090815260046020908152604080832093861683529290522054838114611e34578015611e0a576001600160e01b0319871660009081526002602090815260408083208484529091528120555b6001600160e01b031980881660009081526004602090815260408083209387168352929052208490555b5050505b6001600160e01b03198416600090815260036020526040812054611e7d908490611e71906001600160801b03164263ffffffff61249a16565b9063ffffffff61249a16565b6001600160e01b0319861660009081526003602052604081205491925090611eb6908390600160801b90046001600160801b031661249a565b6001600160e01b03198716600090815260026020908152604080832087845290915290208054919250906001600160801b0316801580611ef557508084115b611f305760405162461bcd60e51b81526004018080602001828103825260288152602001806127c06028913960400191505060405180910390fd5b81546001600160801b03848116600160801b028187166001600160801b03199093169290921716178255604080516001600160e01b03198a16815260208082018790526060820186905260809282018381528a519383019390935289517fd7e6ea5d472293380587e80ee930aaf3dafcb4da900ef39840b525867bb220c4938c9389938d938a939160a08401919086019080838360005b83811015611fdf578181015183820152602001611fc7565b50505050905090810190601f16801561200c5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a15050505050505050565b6001600160e01b0319166000908152600360205260409020546001600160801b031690565b6001600160e01b031916600090815260036020526040902054600160801b90046001600160801b031690565b604080516001600160e01b03198416602082015280820183905281518082038301815260609091019091526120b49063d7ce3c6f60e01b906122f7565b6001600160e01b0319821660009081527f853c0ad41052a6382a89e0e283f5254589d89b8e221fb1b8e970f56802a9c3d8602052604081205561140682826124fb565b60006005600084600481111561210957fe5b8152602081019190915260400160002080549091506001600160a01b03838116911614610b225780546001600160a01b0319166001600160a01b03831617815582600481111561215557fe5b604080516001600160a01b038516815290517f40ab465936efb8324cf37e3a29170c60d9b81de43af89693ce9d92c761e42adc9181900360200190a2505050565b604080516001600160e01b03198416602082015280820183905281518082038301815260609091019091526121d39063e950c08560e01b906122f7565b6001600160e01b0319821660009081527fc62cd2b678eec090e28450ba4c449928bac817050d2c9f2aabe08e7a8043503160205260408120556114068282612603565b600080600080600080866040516020018082805190602001908083835b602083106122525780518252601f199092019160209182019101612233565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835284528151918101919091206001600160e01b03198e16600090815260028352848120828252909252929020546001600160801b03808216801580159d50909950600160801b9092041696509194508993509091506122dc905057508242115b94508580156122ea57508142115b9350509295509295909350565b6000816040516020018082805190602001908083835b6020831061232c5780518252601f19909201916020918201910161230d565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012090506123716126c9565b506001600160e01b0319831660009081526002602090815260408083208484528252918290208251808401909352546001600160801b03808216808552600160801b909204169183018290529081158015906123cd5750428211155b61241e576040805162461bcd60e51b815260206004820152601760248201527f54696d656c6f636b20697320696e636f6d706c6574652e000000000000000000604482015290519081900360640190fd5b42811161246a576040805162461bcd60e51b81526020600482015260156024820152742a34b6b2b637b1b5903430b99032bc3834b932b21760591b604482015290519081900360640190fd5b5050506001600160e01b031990921660009081526002602090815260408083209483529390529182209190915550565b6000828201838110156124f4576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6801b5a660ea44b8000081106125425760405162461bcd60e51b81526004018080602001828103825260328152602001806127486032913960400191505060405180910390fd5b603c81116125815760405162461bcd60e51b81526004018080602001828103825260258152602001806127026025913960400191505060405180910390fd5b6001600160e01b0319821660008181526003602090815260409182902080546001600160801b03868116600160801b90810282841617909355845195865291900416908301819052828201849052905190917f63f1567641b865eea56986985cc3702d7040232ddf6fde052234a17e97cc5889919081900360600190a1505050565b6801b5a660ea44b80000811061264a5760405162461bcd60e51b81526004018080602001828103825260308152602001806127e86030913960400191505060405180910390fd5b6001600160e01b0319821660008181526003602090815260409182902080546001600160801b038681166001600160801b0319831617909255835194855216908301819052828201849052905190917f559d7dd60c597cca6d78f7577a0778cbe3d5fbd56636087e185037f260d83338919081900360600190a1505050565b60408051808201909152600080825260208201529056fe537570706c6965642065787472612074696d6520697320746f6f206c617267652e4e65772074696d656c6f636b2065787069726174696f6e20697320746f6f2073686f72742e4e6f20736d6172742077616c6c657420616464726573732070726f76696465642e537570706c6965642064656661756c742074696d656c6f636b2065787069726174696f6e20697320746f6f206c617267652e54696d656c6f636b20696e74657276616c206f66206d6f6469667954696d656c6f636b496e74657276616c2063616e6e6f7420657863656564206569676874207765656b732e4578697374696e672074696d656c6f636b73206d6179206f6e6c7920626520657874656e6465642e537570706c696564206d696e696d756d2074696d656c6f636b20696e74657276616c20697320746f6f206c617267652e4e6f2074696d656c6f636b20666f756e6420666f722074686520676976656e20617267756d656e74732e43616c6c657220646f6573206e6f742068617665206120726571756972656420726f6c652e54776f537465704f776e61626c653a2063757272656e74206f776e6572206d757374207365742063616c6c6572206173206e657720706f74656e7469616c206f776e65722e546869732077616c6c65742068617320656c656374656420746f206f7074206f7574206f66206163636f756e74207265636f766572792066756e6374696f6e616c6974792e54776f537465704f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65722e537570706c6965642064656661756c742074696d656c6f636b206475726174696f6e20746f206d6f6469667920697320746f6f206c617267652e4e6f206e65772075736572207369676e696e67206b65792070726f76696465642e46756e6374696f6e2073656c6563746f722063616e6e6f7420626520656d7074792e45787069726174696f6e206f66206d6f6469667954696d656c6f636b45787069726174696f6e206d757374206265206174206c6561737420616e20686f7572206c6f6e672e526f6c6520696e207175657374696f6e20697320616c726561647920756e7061757365642e526f6c6520696e207175657374696f6e2069732063757272656e746c79207061757365642e526f6c6520696e207175657374696f6e20697320616c7265616479207061757365642e4e65772074696d656c6f636b2065787069726174696f6e2063616e6e6f7420657863656564206f6e65206d6f6e74682e54776f537465704f776e61626c653a206e657720706f74656e7469616c206f776e657220697320746865207a65726f20616464726573732ea265627a7a7231582020446861726d614163636f756e745265636f766572794d616e6167657256322064736f6c634300050b00324e65772074696d656c6f636b2065787069726174696f6e20697320746f6f2073686f72742e537570706c6965642064656661756c742074696d656c6f636b2065787069726174696f6e20697320746f6f206c617267652e537570706c696564206d696e696d756d2074696d656c6f636b20696e74657276616c20697320746f6f206c617267652e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c80639d003e0411610104578063e950c085116100a2578063f2fde38b11610071578063f2fde38b146105fb578063f5d3b65114610621578063f6e6761e14610647578063fd717de21461067a576101da565b8063e950c0851461049b578063ec2cd043146104c8578063edf07f15146105ac578063f2e12a39146105cc576101da565b8063bc61e733116100de578063bc61e73314610426578063d7ce3c6f14610446578063dab41d0d14610473578063e7f43c6814610493576101da565b80639d003e04146103d7578063afb24ecf146103fe578063bb60332014610406576101da565b806363e0cf4a1161017c57806379ba50971161014b57806379ba5097146103b75780638613959a146103bf5780638da5cb5b146103c75780638f32d59b146103cf576101da565b806363e0cf4a146102f5578063648bf7741461032f57806368a477fc1461035d5780637008b54814610393576101da565b806329904232116101b8578063299042321461023d578063301c7e5d14610269578063336e73d0146102895780635f679530146102c2576101da565b80630f664e6c146101df5780631e225a6e1461020f57806323452b9c14610235575b600080fd5b61020d600480360360408110156101f557600080fd5b506001600160a01b0381358116916020013516610682565b005b61020d6004803603602081101561022557600080fd5b50356001600160a01b031661083c565b61020d6109ae565b61020d6004803603604081101561025357600080fd5b506001600160a01b038135169060200135610a03565b61020d6004803603602081101561027f57600080fd5b503560ff16610b27565b6102b06004803603602081101561029f57600080fd5b50356001600160e01b031916610c1a565b60408051918252519081900360200190f35b61020d600480360360608110156102d857600080fd5b506001600160e01b03198135169060208101359060400135610c2b565b61031b6004803603602081101561030b57600080fd5b50356001600160a01b0316610d4d565b604080519115158252519081900360200190f35b61020d6004803603604081101561034557600080fd5b506001600160a01b0381358116916020013516610d6b565b61020d6004803603606081101561037357600080fd5b506001600160a01b038135811691602081013590911690604001356110e9565b61039b61124e565b604080516001600160a01b039092168252519081900360200190f35b61020d611275565b61039b61131a565b61039b611326565b61031b611335565b6102b0600480360360208110156103ed57600080fd5b50356001600160e01b031916611346565b61039b611351565b61031b6004803603602081101561041c57600080fd5b503560ff1661135d565b61031b6004803603602081101561043c57600080fd5b503560ff16611368565b61020d6004803603604081101561045c57600080fd5b506001600160e01b03198135169060200135611373565b61020d6004803603602081101561048957600080fd5b503560ff1661140a565b61039b61145b565b61020d600480360360408110156104b157600080fd5b506001600160e01b03198135169060200135611466565b61057f600480360360408110156104de57600080fd5b6001600160e01b0319823516919081019060408101602082013564010000000081111561050a57600080fd5b82018360208201111561051c57600080fd5b8035906020019184600183028401116401000000008311171561053e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506114f9945050505050565b60408051951515865293151560208601529115158484015260608401526080830152519081900360a00190f35b61020d600480360360208110156105c257600080fd5b503560ff1661151e565b61020d600480360360408110156105e257600080fd5b50803560ff1690602001356001600160a01b031661166d565b61020d6004803603602081101561061157600080fd5b50356001600160a01b0316611715565b61020d6004803603602081101561063757600080fd5b50356001600160a01b03166117bf565b61020d6004803603606081101561065d57600080fd5b506001600160e01b0319813516906020810135906040013561191d565b61039b611a80565b600261068c611335565b6107195761069981611a8c565b6106d45760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b6106dd81611ac0565b156107195760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b03831661075e5760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6001600160a01b0382166107b9576040805162461bcd60e51b815260206004820152601d60248201527f4e6f2075736572207369676e696e67206b65792070726f76696465642e000000604482015290519081900360640190fd5b604080516001600160a01b03808616602083015284168183015281518082038301815260609091019091526107f690631922fddd60e21b90611af3565b604080516001600160a01b0384811682529151918516917f8506b00cd2df941a18335b7afb79ee5c531dc5cce3972b1b7bdf0211f96d711b9181900360200190a2505050565b6003610846611335565b6108d35761085381611a8c565b61088e5760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61089781611ac0565b156108d35760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b0382166109185760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6109528260405160200180826001600160a01b03166001600160a01b03168152602001915050604051602081830303815290604052611c40565b6001600160a01b038216600081815260066020908152604091829020805460ff19166001179055815192835290517fa6a1c7e9940e618f418f7c47c543aea6144e61d3e65fe63fd64e0edef19d9ac69281900390910190a15050565b6109b6611335565b6109f15760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b600180546001600160a01b0319169055565b6000610a0d611335565b610a9a57610a1a81611a8c565b610a555760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b610a5e81611ac0565b15610a9a5760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b038316610adf5760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b610b22631e225a6e60e01b8460405160200180826001600160a01b03166001600160a01b0316815260200191505060405160208183030381529060405284611c56565b505050565b610b2f611335565b610b6a5760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b600060056000836004811115610b7c57fe5b815260208101919091526040016000208054909150600160a01b900460ff16610bd65760405162461bcd60e51b81526004018080602001828103825260258152602001806129db6025913960400191505060405180910390fd5b805460ff60a01b19168155816004811115610bed57fe5b6040517fd9ff16dcccc040d408ddf47191ae2d5313510993b245b3a7ccfb0258a4401d7890600090a25050565b6000610c2582612026565b92915050565b610c33611335565b610c6e5760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b03198316610cb45760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b6001600160e01b0319831663e950c08560e01b1415610d0f576249d400821115610d0f5760405162461bcd60e51b815260040180806020018281038252604681526020018061277a6046913960600191505060405180910390fd5b604080516001600160e01b0319851660208201528082018490528151808203830181526060909101909152610b229063e950c08560e01b9083611c56565b6001600160a01b031660009081526006602052604090205460ff1690565b6001610d75611335565b610e0257610d8281611a8c565b610dbd5760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b610dc681611ac0565b15610e025760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b038316610e475760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6001600160a01b038216610e8c5760405162461bcd60e51b81526004018080602001828103825260218152602001806129536021913960400191505060405180910390fd5b6001600160a01b03831660009081526006602052604090205460ff1615610ee45760405162461bcd60e51b81526004018080602001828103825260458152602001806128ac6045913960600191505060405180910390fd5b604080516001600160a01b0380861660208301528416818301528151808203830181526060909101909152610f1890611c40565b60008060006060866001600160a01b031660025a81610f3357fe5b60408051600481526024810182526020810180516001600160e01b031663081a078d60e41b17815291518151949093049390929182918083835b60208310610f8c5780518252601f199092019160209182019101610f6d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114610fef576040519150601f19603f3d011682016040523d82523d6000602084013e610ff4565b606091505b5091509150818015611007575080516020145b156110265780806020019051602081101561102157600080fd5b505192505b866001600160a01b0316630cd865ec876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b15801561107e57600080fd5b505af1158015611092573d6000803e3d6000fd5b5050604080516001600160a01b0387811682528a811660208301528251908c1694507f6c0468512076e943ed3d1c5aae1d6903c72162713d86aedd1381b3ac19e10cec93509081900390910190a250505050505050565b60006110f3611335565b6111805761110081611a8c565b61113b5760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61114481611ac0565b156111805760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b0384166111c55760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6001600160a01b03831661120a5760405162461bcd60e51b81526004018080602001828103825260218152602001806129536021913960400191505060405180910390fd5b604080516001600160a01b038087166020830152851681830152815180820383018152606090910190915261124890631922fddd60e21b9084611c56565b50505050565b600060058160045b81526020810191909152604001600020546001600160a01b0316919050565b6001546001600160a01b031633146112be5760405162461bcd60e51b81526004018080602001828103825260458152602001806128676045913960600191505060405180910390fd5b600180546001600160a01b03191690556000805460405133926001600160a01b03909216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03191633179055565b60006005816002611256565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b6000610c258261204b565b60006005816003611256565b6000610c2582611a8c565b6000610c2582611ac0565b61137b611335565b6113b65760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b031982166113fc5760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b6114068282612077565b5050565b611412611335565b61144d5760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6114588160006120f7565b50565b600060058180611256565b61146e611335565b6114a95760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b031982166114ef5760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b6114068282612196565b600080600080600061150b8787612216565b939b929a50909850965090945092505050565b6004611528611335565b6115b55761153581611a8c565b6115705760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61157981611ac0565b156115b55760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6000600560008460048111156115c757fe5b815260208101919091526040016000208054909150600160a01b900460ff16156116225760405162461bcd60e51b8152600401808060200182810382526023815260200180612a256023913960400191505060405180910390fd5b805460ff60a01b1916600160a01b17815582600481111561163f57fe5b6040517fad75709c5a2559beeed6c59693a5ea8701185d51947d3eef38713bb0fe5891e990600090a2505050565b611675611335565b6116b05760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160a01b03811661170b576040805162461bcd60e51b815260206004820152601760248201527f4d75737420737570706c7920616e206163636f756e742e000000000000000000604482015290519081900360640190fd5b61140682826120f7565b61171d611335565b6117585760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160a01b03811661179d5760405162461bcd60e51b8152600401808060200182810382526038815260200180612a786038913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60026117c9611335565b611856576117d681611a8c565b6118115760405162461bcd60e51b81526004018080602001828103825260258152602001806128426025913960400191505060405180910390fd5b61181a81611ac0565b156118565760405162461bcd60e51b8152600401808060200182810382526025815260200180612a006025913960400191505060405180910390fd5b6001600160a01b03821661189b5760405162461bcd60e51b81526004018080602001828103825260218152602001806127276021913960400191505060405180910390fd5b6118dd631e225a6e60e01b8360405160200180826001600160a01b03166001600160a01b03168152602001915050604051602081830303815290604052611af3565b604080516001600160a01b038416815290517f170985b339d7db71b7658093224871db8b69f5728f1f0c45459af399728b54db9181900360200190a15050565b611925611335565b6119605760405162461bcd60e51b81526004018080602001828103825260288152602001806128f16028913960400191505060405180910390fd5b6001600160e01b031983166119a65760405162461bcd60e51b81526004018080602001828103825260228152602001806129746022913960400191505060405180910390fd5b62278d008211156119e85760405162461bcd60e51b8152600401808060200182810382526030815260200180612a486030913960400191505060405180910390fd5b6001600160e01b0319831663d7ce3c6f60e01b1415611a4257610e10821015611a425760405162461bcd60e51b81526004018080602001828103825260458152602001806129966045913960600191505060405180910390fd5b604080516001600160e01b0319851660208201528082018490528151808203830181526060909101909152610b229063d7ce3c6f60e01b9083611c56565b60006005816001611256565b600060056000836004811115611a9e57fe5b81526020810191909152604001600020546001600160a01b0316331492915050565b600060056000836004811115611ad257fe5b8152602081019190915260400160002054600160a01b900460ff1692915050565b6000816040516020018082805190602001908083835b60208310611b285780518252601f199092019160209182019101611b09565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835284528151918101919091206001600160e01b0319891660009081526002835284812082825290925292902080549295509350506001600160801b038082169250600160801b9091041681611bd85760405162461bcd60e51b815260040180806020018281038252602a815260200180612818602a913960400191505060405180910390fd5b428111611c2c576040805162461bcd60e51b815260206004820152601d60248201527f54696d656c6f636b2068617320616c726561647920657870697265642e000000604482015290519081900360640190fd5b505080546001600160801b03169055505050565b6114586000356001600160e01b031916826122f7565b6801b5a660ea44b800008110611c9d5760405162461bcd60e51b81526004018080602001828103825260218152602001806126e16021913960400191505060405180910390fd5b6000826040516020018082805190602001908083835b60208310611cd25780518252601f199092019160209182019101611cb3565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f19018352909352805192019190912093505063e950c08560e01b6001600160e01b03198716149150819050611d3e57506001600160e01b0319841663d7ce3c6f60e01b145b15611e3857600080848060200190516040811015611d5b57600080fd5b50805160209091015190925090506801b5a660ea44b800008110611db05760405162461bcd60e51b815260040180806020018281038252603a815260200180612919603a913960400191505060405180910390fd5b6001600160e01b0319808716600090815260046020908152604080832093861683529290522054838114611e34578015611e0a576001600160e01b0319871660009081526002602090815260408083208484529091528120555b6001600160e01b031980881660009081526004602090815260408083209387168352929052208490555b5050505b6001600160e01b03198416600090815260036020526040812054611e7d908490611e71906001600160801b03164263ffffffff61249a16565b9063ffffffff61249a16565b6001600160e01b0319861660009081526003602052604081205491925090611eb6908390600160801b90046001600160801b031661249a565b6001600160e01b03198716600090815260026020908152604080832087845290915290208054919250906001600160801b0316801580611ef557508084115b611f305760405162461bcd60e51b81526004018080602001828103825260288152602001806127c06028913960400191505060405180910390fd5b81546001600160801b03848116600160801b028187166001600160801b03199093169290921716178255604080516001600160e01b03198a16815260208082018790526060820186905260809282018381528a519383019390935289517fd7e6ea5d472293380587e80ee930aaf3dafcb4da900ef39840b525867bb220c4938c9389938d938a939160a08401919086019080838360005b83811015611fdf578181015183820152602001611fc7565b50505050905090810190601f16801561200c5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a15050505050505050565b6001600160e01b0319166000908152600360205260409020546001600160801b031690565b6001600160e01b031916600090815260036020526040902054600160801b90046001600160801b031690565b604080516001600160e01b03198416602082015280820183905281518082038301815260609091019091526120b49063d7ce3c6f60e01b906122f7565b6001600160e01b0319821660009081527f853c0ad41052a6382a89e0e283f5254589d89b8e221fb1b8e970f56802a9c3d8602052604081205561140682826124fb565b60006005600084600481111561210957fe5b8152602081019190915260400160002080549091506001600160a01b03838116911614610b225780546001600160a01b0319166001600160a01b03831617815582600481111561215557fe5b604080516001600160a01b038516815290517f40ab465936efb8324cf37e3a29170c60d9b81de43af89693ce9d92c761e42adc9181900360200190a2505050565b604080516001600160e01b03198416602082015280820183905281518082038301815260609091019091526121d39063e950c08560e01b906122f7565b6001600160e01b0319821660009081527fc62cd2b678eec090e28450ba4c449928bac817050d2c9f2aabe08e7a8043503160205260408120556114068282612603565b600080600080600080866040516020018082805190602001908083835b602083106122525780518252601f199092019160209182019101612233565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835284528151918101919091206001600160e01b03198e16600090815260028352848120828252909252929020546001600160801b03808216801580159d50909950600160801b9092041696509194508993509091506122dc905057508242115b94508580156122ea57508142115b9350509295509295909350565b6000816040516020018082805190602001908083835b6020831061232c5780518252601f19909201916020918201910161230d565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012090506123716126c9565b506001600160e01b0319831660009081526002602090815260408083208484528252918290208251808401909352546001600160801b03808216808552600160801b909204169183018290529081158015906123cd5750428211155b61241e576040805162461bcd60e51b815260206004820152601760248201527f54696d656c6f636b20697320696e636f6d706c6574652e000000000000000000604482015290519081900360640190fd5b42811161246a576040805162461bcd60e51b81526020600482015260156024820152742a34b6b2b637b1b5903430b99032bc3834b932b21760591b604482015290519081900360640190fd5b5050506001600160e01b031990921660009081526002602090815260408083209483529390529182209190915550565b6000828201838110156124f4576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6801b5a660ea44b8000081106125425760405162461bcd60e51b81526004018080602001828103825260328152602001806127486032913960400191505060405180910390fd5b603c81116125815760405162461bcd60e51b81526004018080602001828103825260258152602001806127026025913960400191505060405180910390fd5b6001600160e01b0319821660008181526003602090815260409182902080546001600160801b03868116600160801b90810282841617909355845195865291900416908301819052828201849052905190917f63f1567641b865eea56986985cc3702d7040232ddf6fde052234a17e97cc5889919081900360600190a1505050565b6801b5a660ea44b80000811061264a5760405162461bcd60e51b81526004018080602001828103825260308152602001806127e86030913960400191505060405180910390fd5b6001600160e01b0319821660008181526003602090815260409182902080546001600160801b038681166001600160801b0319831617909255835194855216908301819052828201849052905190917f559d7dd60c597cca6d78f7577a0778cbe3d5fbd56636087e185037f260d83338919081900360600190a1505050565b60408051808201909152600080825260208201529056fe537570706c6965642065787472612074696d6520697320746f6f206c617267652e4e65772074696d656c6f636b2065787069726174696f6e20697320746f6f2073686f72742e4e6f20736d6172742077616c6c657420616464726573732070726f76696465642e537570706c6965642064656661756c742074696d656c6f636b2065787069726174696f6e20697320746f6f206c617267652e54696d656c6f636b20696e74657276616c206f66206d6f6469667954696d656c6f636b496e74657276616c2063616e6e6f7420657863656564206569676874207765656b732e4578697374696e672074696d656c6f636b73206d6179206f6e6c7920626520657874656e6465642e537570706c696564206d696e696d756d2074696d656c6f636b20696e74657276616c20697320746f6f206c617267652e4e6f2074696d656c6f636b20666f756e6420666f722074686520676976656e20617267756d656e74732e43616c6c657220646f6573206e6f742068617665206120726571756972656420726f6c652e54776f537465704f776e61626c653a2063757272656e74206f776e6572206d757374207365742063616c6c6572206173206e657720706f74656e7469616c206f776e65722e546869732077616c6c65742068617320656c656374656420746f206f7074206f7574206f66206163636f756e74207265636f766572792066756e6374696f6e616c6974792e54776f537465704f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65722e537570706c6965642064656661756c742074696d656c6f636b206475726174696f6e20746f206d6f6469667920697320746f6f206c617267652e4e6f206e65772075736572207369676e696e67206b65792070726f76696465642e46756e6374696f6e2073656c6563746f722063616e6e6f7420626520656d7074792e45787069726174696f6e206f66206d6f6469667954696d656c6f636b45787069726174696f6e206d757374206265206174206c6561737420616e20686f7572206c6f6e672e526f6c6520696e207175657374696f6e20697320616c726561647920756e7061757365642e526f6c6520696e207175657374696f6e2069732063757272656e746c79207061757365642e526f6c6520696e207175657374696f6e20697320616c7265616479207061757365642e4e65772074696d656c6f636b2065787069726174696f6e2063616e6e6f7420657863656564206f6e65206d6f6e74682e54776f537465704f776e61626c653a206e657720706f74656e7469616c206f776e657220697320746865207a65726f20616464726573732ea265627a7a7231582020446861726d614163636f756e745265636f766572794d616e6167657256322064736f6c634300050b0032

Deployed Bytecode Sourcemap

31585:21456:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31585:21456:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38305:592;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;38305:592:0;;;;;;;;;;:::i;:::-;;37400:554;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37400:554:0;-1:-1:-1;;;;;37400:554:0;;:::i;7893:90::-;;;:::i;36570:386::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;36570:386:0;;;;;;;;:::i;40630:267::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40630:267:0;;;;:::i;12735:209::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12735:209:0;-1:-1:-1;;;;;;12735:209:0;;:::i;:::-;;;;;;;;;;;;;;;;41331:851;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;;41331:851:0;;;;;;;;;;;;;:::i;46934:278::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46934:278:0;-1:-1:-1;;;;;46934:278:0;;:::i;:::-;;;;;;;;;;;;;;;;;;34451:1475;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;34451:1475:0;;;;;;;;;;:::i;33644:481::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;33644:481:0;;;;;;;;;;;;;;;;;:::i;50748:118::-;;;:::i;:::-;;;;-1:-1:-1;;;;;50748:118:0;;;;;;;;;;;;;;8141:298;;;:::i;49669:130::-;;;:::i;6980:73::-;;;:::i;7322:86::-;;;:::i;13226:217::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13226:217:0;-1:-1:-1;;;;;;13226:217:0;;:::i;50187:126::-;;;:::i;48291:100::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48291:100:0;;;;:::i;47856:102::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47856:102:0;;;;:::i;45103:479::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;;45103:479:0;;;;;;;;:::i;46529:89::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46529:89:0;;;;:::i;48702:126::-;;;:::i;42633:455::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;;42633:455:0;;;;;;;;:::i;12042:417::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12042:417:0;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;12042:417:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;12042:417:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;12042:417:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;12042:417:0;;-1:-1:-1;12042:417:0;;-1:-1:-1;;;;;12042:417:0:i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40074:276;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40074:276:0;;;;:::i;45991:164::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45991:164:0;;;;;;;;-1:-1:-1;;;;;45991:164:0;;:::i;7541:225::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;7541:225:0;-1:-1:-1;;;;;7541:225:0;;:::i;39185:508::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;39185:508:0;-1:-1:-1;;;;;39185:508:0;;:::i;43582:1065::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;;43582:1065:0;;;;;;;;;;;;;:::i;49197:130::-;;;:::i;38305:592::-;38412:14;52859:9;:7;:9::i;:::-;52854:171;;52887:13;52895:4;52887:7;:13::i;:::-;52879:63;;;;-1:-1:-1;;;52879:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52960:15;52970:4;52960:9;:15::i;:::-;52959:16;52951:66;;;;-1:-1:-1;;;52951:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38443:25:0;;38435:71;;;;-1:-1:-1;;;38435:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38521:28:0;;38513:70;;;;;-1:-1:-1;;;38513:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;38719:39;;;-1:-1:-1;;;;;38719:39:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;38719:39:0;;;;;;;38672:93;;-1:-1:-1;;;38696:21:0;38672:15;:93::i;:::-;38845:46;;;-1:-1:-1;;;;;38845:46:0;;;;;;;;;;;;;;;;;;;;38305:592;;;:::o;37400:554::-;37484:13;52859:9;:7;:9::i;:::-;52854:171;;52887:13;52895:4;52887:7;:13::i;:::-;52879:63;;;;-1:-1:-1;;;52879:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52960:15;52970:4;52960:9;:15::i;:::-;52959:16;52951:66;;;;-1:-1:-1;;;52951:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37514:25:0;;37506:71;;;;-1:-1:-1;;;37506:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37650:41;37678:11;37667:23;;;;;;-1:-1:-1;;;;;37667:23:0;-1:-1:-1;;;;;37667:23:0;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;37667:23:0;;;37650:16;:41::i;:::-;-1:-1:-1;;;;;37779:37:0;;;;;;:24;:37;;;;;;;;;:44;;-1:-1:-1;;37779:44:0;37819:4;37779:44;;;37919:29;;;;;;;;;;;;;;;;;37400:554;;:::o;7893:90::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7959:18;7952:25;;-1:-1:-1;;;;;;7952:25:0;;;7893:90::o;36570:386::-;36685:13;52859:9;:7;:9::i;:::-;52854:171;;52887:13;52895:4;52887:7;:13::i;:::-;52879:63;;;;-1:-1:-1;;;52879:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52960:15;52970:4;52960:9;:15::i;:::-;52959:16;52951:66;;;;-1:-1:-1;;;52951:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;36715:25:0;;36707:71;;;;-1:-1:-1;;;36707:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36850:100;36871:36;;;36920:11;36909:23;;;;;;-1:-1:-1;;;;;36909:23:0;-1:-1:-1;;;;;36909:23:0;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;36909:23:0;;;36934:9;36850:12;:100::i;:::-;36570:386;;;:::o;40630:267::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40684:35;40722:6;:21;40737:4;40729:13;;;;;;;;40722:21;;;;;;;;;;;-1:-1:-1;40722:21:0;40758:23;;40722:21;;-1:-1:-1;;;;40758:23:0;;;;40750:73;;;;-1:-1:-1;;;40750:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40830:31;;-1:-1:-1;;;;40830:31:0;;;40886:4;40873:18;;;;;;;;;;;;;;;7235:1;40630:267;:::o;12735:209::-;12827:31;12893:45;12921:16;12893:27;:45::i;:::-;12867:71;12735:209;-1:-1:-1;;12735:209:0:o;41331:851::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;41575:29:0;;41559:97;;;;-1:-1:-1;;;41559:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;41750:56:0;;-1:-1:-1;;;41750:56:0;41746:219;;;41858:7;41835:19;:30;;41817:140;;;;-1:-1:-1;;;41817:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42102:49;;;-1:-1:-1;;;;;;42102:49:0;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;42102::0;;;;;;;42036:140;;-1:-1:-1;;;42057:36:0;42160:9;42036:12;:140::i;46934:278::-;-1:-1:-1;;;;;47169:37:0;47021:31;47169:37;;;:24;:37;;;;;;;;;46934:278::o;34451:1475::-;34547:14;52859:9;:7;:9::i;:::-;52854:171;;52887:13;52895:4;52887:7;:13::i;:::-;52879:63;;;;-1:-1:-1;;;52879:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52960:15;52970:4;52960:9;:15::i;:::-;52959:16;52951:66;;;;-1:-1:-1;;;52951:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;34578:25:0;;34570:71;;;;-1:-1:-1;;;34570:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;34664:31:0;;34648:98;;;;-1:-1:-1;;;34648:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;34854:37:0;;;;;;:24;:37;;;;;;;;34853:38;34837:141;;;;-1:-1:-1;;;34837:141:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35068:42;;;-1:-1:-1;;;;;35068:42:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;35068:42:0;;;;;;;35051:60;;:16;:60::i;:::-;35191:50;35332:25;35365:7;35374:17;35395:11;-1:-1:-1;;;;;35395:16:0;35428:1;35416:9;:13;;;;;35439:66;;;22:32:-1;6:49;;35439:66:0;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;35395:117:0;;;;35416:13;;;;;35439:66;;35395:117;;;;;25:18:-1;36:153;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;35395:117:0;;;;;;;;;;;;;;;;;;;;;;;;;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;;35364:148:0;;;;35523:2;:23;;;;;35529:4;:11;35544:2;35529:17;35523:23;35519:93;;;35588:4;35577:27;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35577:27:0;;-1:-1:-1;35519:93:0;35732:11;-1:-1:-1;;;;;35697:55:0;;35753:17;35697:74;;;;;;;;;;;;;-1:-1:-1;;;;;35697:74:0;-1:-1:-1;;;;;35697:74:0;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;35697:74:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;35861:59:0;;;-1:-1:-1;;;;;35861:59:0;;;;;;;;;;;;;;;;;;-1:-1:-1;35861:59:0;;-1:-1:-1;35861:59:0;;;;;;;;;53031:1;;;;34451:1475;;;:::o;33644:481::-;33772:13;52859:9;:7;:9::i;:::-;52854:171;;52887:13;52895:4;52887:7;:13::i;:::-;52879:63;;;;-1:-1:-1;;;52879:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52960:15;52970:4;52960:9;:15::i;:::-;52959:16;52951:66;;;;-1:-1:-1;;;52951:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33802:25:0;;33794:71;;;;-1:-1:-1;;;33794:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33880:28:0;;33872:74;;;;-1:-1:-1;;;33872:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34062:39;;;-1:-1:-1;;;;;34062:39:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;34062:39:0;;;;;;;34018:101;;-1:-1:-1;;;34039:21:0;34103:9;34018:12;:101::i;:::-;33644:481;;;;:::o;50748:118::-;50792:14;50824:6;50792:14;50839:11;50831:20;50824:28;;;;;;;;;;;-1:-1:-1;50824:28:0;:36;-1:-1:-1;;;;;50824:36:0;;50748:118;-1:-1:-1;50748:118:0:o;8141:298::-;8212:18;;-1:-1:-1;;;;;8212:18:0;8198:10;:32;8182:135;;;;-1:-1:-1;;;8182:135:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8333:18;8326:25;;-1:-1:-1;;;;;;8326:25:0;;;-1:-1:-1;8386:6:0;;8365:40;;8394:10;;-1:-1:-1;;;;;8386:6:0;;;;8365:40;;;8414:6;:19;;-1:-1:-1;;;;;;8414:19:0;8423:10;8414:19;;;8141:298::o;49669:130::-;49716:17;49754:6;49716:17;49769:14;49761:23;;6980:73;7018:7;7041:6;-1:-1:-1;;;;;7041:6:0;6980:73;:::o;7322:86::-;7362:4;7396:6;-1:-1:-1;;;;;7396:6:0;7382:10;:20;;7322:86::o;13226:217::-;13320:33;13390:47;13420:16;13390:29;:47::i;50187:126::-;50233:16;50269:6;50233:16;50284:13;50276:22;;48291:100;48341:12;48372:13;48380:4;48372:7;:13::i;47856:102::-;47908:11;47937:15;47947:4;47937:9;:15::i;45103:479::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;45324:29:0;;45308:97;;;;-1:-1:-1;;;45308:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45496:80;45530:16;45548:21;45496:25;:80::i;:::-;45103:479;;:::o;46529:89::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46586:26;46595:4;46609:1;46586:8;:26::i;:::-;46529:89;:::o;48702:126::-;48748:16;48784:6;48748:16;;48791:22;;42633:455;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;42850:29:0;;42834:97;;;;-1:-1:-1;;;42834:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43020:62;43044:16;43062:19;43020:23;:62::i;12042:417::-;12149:11;12167:14;12188:12;12207:22;12236;12398:55;12419:16;12437:9;12398:12;:55::i;:::-;12335:118;;;;-1:-1:-1;12335:118:0;;-1:-1:-1;12335:118:0;-1:-1:-1;12335:118:0;;-1:-1:-1;12042:417:0;-1:-1:-1;;;12042:417:0:o;40074:276::-;40121:11;52859:9;:7;:9::i;:::-;52854:171;;52887:13;52895:4;52887:7;:13::i;:::-;52879:63;;;;-1:-1:-1;;;52879:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52960:15;52970:4;52960:9;:15::i;:::-;52959:16;52951:66;;;;-1:-1:-1;;;52951:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40141:35;40179:6;:21;40194:4;40186:13;;;;;;;;40179:21;;;;;;;;;;;-1:-1:-1;40179:21:0;40216:23;;40179:21;;-1:-1:-1;;;;40216:23:0;;;;40215:24;40207:72;;;;-1:-1:-1;;;40207:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40286:30;;-1:-1:-1;;;;40286:30:0;-1:-1:-1;;;40286:30:0;;;40339:4;40328:16;;;;;;;;;;;;;;;53031:1;40074:276;;:::o;45991:164::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;46070:21:0;;46062:57;;;;;-1:-1:-1;;;46062:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;46126:23;46135:4;46141:7;46126:8;:23::i;7541:225::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7626:22:0;;7610:112;;;;-1:-1:-1;;;7610:112:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7731:18;:29;;-1:-1:-1;;;;;;7731:29:0;-1:-1:-1;;;;;7731:29:0;;;;;;;;;;7541:225::o;39185:508::-;39279:14;52859:9;:7;:9::i;:::-;52854:171;;52887:13;52895:4;52887:7;:13::i;:::-;52879:63;;;;-1:-1:-1;;;52879:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52960:15;52970:4;52960:9;:15::i;:::-;52959:16;52951:66;;;;-1:-1:-1;;;52951:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39310:25:0;;39302:71;;;;-1:-1:-1;;;39302:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39462:92;39486:36;;;39535:11;39524:23;;;;;;-1:-1:-1;;;;;39524:23:0;-1:-1:-1;;;;;39524:23:0;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;39524:23:0;;;39462:15;:92::i;:::-;39646:41;;;-1:-1:-1;;;;;39646:41:0;;;;;;;;;;;;;;;39185:508;;:::o;43582:1065::-;7174:9;:7;:9::i;:::-;7166:62;;;;-1:-1:-1;;;7166:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;43830:29:0;;43814:97;;;;-1:-1:-1;;;43814:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44038:7;44013:21;:32;;43997:114;;;;-1:-1:-1;;;43997:114:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;44205:58:0;;-1:-1:-1;;;44205:58:0;44201:225;;;44317:10;44292:21;:35;;44274:144;;;;-1:-1:-1;;;44274:144:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44565:51;;;-1:-1:-1;;;;;;44565:51:0;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;44565:51:0;;;;;;;44497:144;;-1:-1:-1;;;44518:38:0;44625:9;44497:12;:144::i;49197:130::-;49244:17;49282:6;49244:17;49297:14;49289:23;;51858:131;51909:12;51954:6;:21;51969:4;51961:13;;;;;;;;51954:21;;;;;;;;;;;-1:-1:-1;51954:21:0;:29;-1:-1:-1;;;;;51954:29:0;51940:10;:43;;;-1:-1:-1;;51858:131:0:o;52318:116::-;52371:11;52400:6;:21;52415:4;52407:13;;;;;;;;52400:21;;;;;;;;;;;-1:-1:-1;52400:21:0;:28;-1:-1:-1;;;52400:28:0;;;;;;-1:-1:-1;;52318:116:0:o;22178:834::-;22341:18;22389:9;22372:27;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;22372:27:0;;;;;;;26:21:-1;;;-1:-1;;22:32;6:49;;22372:27:0;;22362:38;;;;;;;;;-1:-1:-1;;;;;;22486:28:0;;-1:-1:-1;22486:28:0;;;:10;:28;;;;;:40;;;;;;;;;22569:17;;22362:38;;-1:-1:-1;22486:40:0;-1:-1:-1;;;;;;;22569:17:0;;;;-1:-1:-1;;;;22623:16:0;;;;22569:17;22730:75;;;;-1:-1:-1;;;22730:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22893:3;22880:10;:16;22872:58;;;;;-1:-1:-1;;;22872:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;22977:29:0;;-1:-1:-1;;;;;22977:29:0;;;-1:-1:-1;;;22178:834:0:o;23355:154::-;23460:43;23484:7;;-1:-1:-1;;;;;;23484:7:0;23493:9;23460:23;:43::i;14257:3364::-;10955:20;14460:9;:29;14452:75;;;;-1:-1:-1;;;14452:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14599:18;14647:9;14630:27;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;14630:27:0;;;;;;;26:21:-1;;;-1:-1;;22:32;6:49;;14630:27:0;;;14620:38;;;;;;;;;-1:-1:-1;;;;;;;;;;;14834:54:0;;;;-1:-1:-1;14834:54:0;;-1:-1:-1;14834:121:0;;-1:-1:-1;;;;;;;14899:56:0;;-1:-1:-1;;;14899:56:0;14834:121;14822:1250;;;15045:23;15070:16;15111:9;15090:58;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15090:58:0;;;;;;;;;-1:-1:-1;15090:58:0;-1:-1:-1;10955:20:0;15259:28;;15241:126;;;;-1:-1:-1;;;15241:126:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;15496:39:0;;;15457:25;15496:39;;;:21;:39;;;;;;;;:57;;;;;;;;;;15655:31;;;15651:414;;15784:31;;15780:116;;-1:-1:-1;;;;;;15837:28:0;;;;;;:10;:28;;;;;;;;:47;;;;;;;;15830:54;15780:116;-1:-1:-1;;;;;;15985:39:0;;;;;;;:21;:39;;;;;;;;:57;;;;;;;;;:70;;;15651:414;14822:1250;;;;-1:-1:-1;;;;;;16196:35:0;;16161:16;16196:35;;;:17;:35;;;;;:44;16180:91;;16261:9;;16180:76;;-1:-1:-1;;;;;16196:44:0;16252:3;16180:76;:71;:76;:::i;:::-;:80;:91;:80;:91;:::i;:::-;-1:-1:-1;;;;;;16412:35:0;;16362:18;16412:35;;;:17;:35;;;;;:46;16161:110;;-1:-1:-1;16362:18:0;16383:83;;16161:110;;-1:-1:-1;;;16412:46:0;;-1:-1:-1;;;;;16412:46:0;16383:12;:83::i;:::-;-1:-1:-1;;;;;;16559:28:0;;16524:32;16559:28;;;:10;:28;;;;;;;;:40;;;;;;;;16698:24;;16362:104;;-1:-1:-1;16559:40:0;-1:-1:-1;;;;;16698:24:0;17179:20;;;:50;;;17214:15;17203:8;:26;17179:50;17163:124;;;;-1:-1:-1;;;17163:124:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17377:44;;-1:-1:-1;;;;;17428:45:0;;;-1:-1:-1;;;17428:45:0;17377:44;;;-1:-1:-1;;;;;;17377:44:0;;;;;;;17428:45;;;;17547:68;;;-1:-1:-1;;;;;;17547:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17565:16;;17412:8;;17593:9;;17462:10;;17547:68;;;;;;;;;;;;17377:24;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;17547:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14257:3364;;;;;;;;:::o;24922:234::-;-1:-1:-1;;;;;;25099:35:0;25017:31;25099:35;;;:17;:35;;;;;:44;-1:-1:-1;;;;;25099:44:0;;24922:234::o;25447:242::-;-1:-1:-1;;;;;;25630:35:0;25544:33;25630:35;;;:17;:35;;;;;:46;-1:-1:-1;;;25630:46:0;;-1:-1:-1;;;;;25630:46:0;;25447:242::o;19413:667::-;19671:51;;;-1:-1:-1;;;;;;19671:51:0;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;19671:51:0;;;;;;;19594:135;;-1:-1:-1;;;10797:28:0;19594:23;:135::i;:::-;-1:-1:-1;;;;;;19822:91:0;;:73;:91;;;:73;;:91;:73;:91;;19815:98;20004:70;19896:16;20052:21;20004:29;:70::i;51257:268::-;51319:35;51357:6;:21;51372:4;51364:13;;;;;;;;51357:21;;;;;;;;;;;-1:-1:-1;51357:21:0;51402:24;;51357:21;;-1:-1:-1;;;;;;51391:35:0;;;51402:24;;51391:35;51387:133;;51437:34;;-1:-1:-1;;;;;;51437:34:0;-1:-1:-1;;;;;51437:34:0;;;;;51498:4;51485:27;;;;;;;;;;;-1:-1:-1;;;;;51485:27:0;;;;;;;;;;;;;;;51257:268;;;:::o;18103:650::-;18355:49;;;-1:-1:-1;;;;;;18355:49:0;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;18355::0;;;;;;;18280:131;;-1:-1:-1;;;10629:28:0;18280:23;:131::i;:::-;-1:-1:-1;;;;;;18504:89:0;;:71;:89;;;:71;;:89;:71;:89;;18497:96;18681:66;18576:16;18727:19;18681:27;:66::i;23917:720::-;24027:11;24045:14;24066:12;24085:22;24114;24212:18;24260:9;24243:27;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;24243:27:0;;;;;;;26:21:-1;;;-1:-1;;22:32;6:49;;24243:27:0;;24233:38;;;;;;;;;-1:-1:-1;;;;;;24369:28:0;;-1:-1:-1;24369:28:0;;;:10;:28;;;;;:40;;;;;;;;;:49;-1:-1:-1;;;;;24369:49:0;;;24435:19;;;;;-1:-1:-1;24369:49:0;;-1:-1:-1;;;;24486:48:0;;;;;-1:-1:-1;24233:38:0;;-1:-1:-1;24435:19:0;;-1:-1:-1;24435:19:0;;-1:-1:-1;24554:30:0;;-1:-1:-1;24554:30:0;;24570:14;24564:3;:20;24554:30;24542:42;;24601:6;:30;;;;;24617:14;24611:3;:20;24601:30;24591:40;;23917:720;;;;;;;;;:::o;26016:872::-;26186:18;26234:9;26217:27;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;26217:27:0;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;26217:27:0;;;26207:38;;;;;;26186:59;;26303:24;;:::i;:::-;-1:-1:-1;;;;;;;26330:28:0;;;;;;:10;:28;;;;;;;;:40;;;;;;;;;26303:67;;;;;;;;;-1:-1:-1;;;;;26303:67:0;;;;;;-1:-1:-1;;;26303:67:0;;;;;;;;;;;26568:20;;;;;:46;;;26611:3;26592:15;:22;;26568:46;26552:96;;;;;-1:-1:-1;;;26552:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;26728:3;26715:10;:16;26707:50;;;;;-1:-1:-1;;;26707:50:0;;;;;;;;;;;;-1:-1:-1;;;26707:50:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;26842:28:0;;;;;;;:10;:28;;;;;;;;:40;;;;;;;;;26835:47;;;;-1:-1:-1;26016:872:0:o;5072:167::-;5130:7;5158:5;;;5178:6;;;;5170:46;;;;;-1:-1:-1;;;5170:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;5232:1;5072:167;-1:-1:-1;;;5072:167:0:o;28368:1043::-;10955:20;28586:21;:41;28570:125;;;;-1:-1:-1;;;28570:125:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28810:9;28786:21;:33;28770:104;;;;-1:-1:-1;;;28770:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;28985:35:0;;28937:29;28985:35;;;:17;:35;;;;;;;;;:46;;-1:-1:-1;;;;;29112:93:0;;;-1:-1:-1;;;29112:93:0;;;;;;;;;;29301:104;;;;;28985:46;;;;29301:104;;;;;;;;;;;;;;28985:46;;29301:104;;;;;;;;;;28368:1043;;;:::o;27215:820::-;10955:20;27427:19;:39;27411:121;;;;-1:-1:-1;;;27411:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;27639:35:0;;27593:27;27639:35;;;:17;:35;;;;;;;;;:44;;-1:-1:-1;;;;;27762:75:0;;;-1:-1:-1;;;;;;27762:75:0;;;;;;27931:98;;;;;27639:44;27931:98;;;;;;;;;;;;;;27639:44;;27931:98;;;;;;;;;;27215:820;;;:::o;31585:21456::-;;;;;;;;;;-1:-1:-1;31585:21456:0;;;;;;;;:::o

Swarm Source

bzzr://20446861726d614163636f756e745265636f766572794d616e61676572563220

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
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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