ETH Price: $2,111.47 (-10.31%)

Contract

0x199f7FCFaE24C413897bE8ab5477950847Cd3F0f
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Finalize Dharma ...95675432020-02-27 19:32:171827 days ago1582831937IN
0x199f7FCF...847Cd3F0f
0 ETH0.0006161220
Finalize Dharma ...95675222020-02-27 19:28:461827 days ago1582831726IN
0x199f7FCF...847Cd3F0f
0 ETH0.0006161220
Finalize Dharma ...95675082020-02-27 19:26:041827 days ago1582831564IN
0x199f7FCF...847Cd3F0f
0 ETH0.0006161220
Finalize Dharma ...95675072020-02-27 19:25:031827 days ago1582831503IN
0x199f7FCF...847Cd3F0f
0 ETH0.0006161220
Trade D Dai For ...95674292020-02-27 19:04:561827 days ago1582830296IN
0x199f7FCF...847Cd3F0f
0 ETH0.007722558.1
Trade D Dai For ...95674282020-02-27 19:04:231827 days ago1582830263IN
0x199f7FCF...847Cd3F0f
0 ETH0.00930258.1
Trade USDC For D...95673972020-02-27 18:56:141827 days ago1582829774IN
0x199f7FCF...847Cd3F0f
0 ETH0.007411438.1
Set Role95673732020-02-27 18:51:551827 days ago1582829515IN
0x199f7FCF...847Cd3F0f
0 ETH0.000373688.1
Set Role95673652020-02-27 18:50:461827 days ago1582829446IN
0x199f7FCF...847Cd3F0f
0 ETH0.000373588.1

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DharmaReserveManagerV2Staging

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 2020-02-27
*/

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


interface DharmaReserveManagerV2Interface {
  event RoleModified(Role indexed role, address account);
  event RolePaused(Role indexed role);
  event RoleUnpaused(Role indexed role);

  enum Role {
    DEPOSIT_MANAGER,
    ADJUSTER,
    PAUSER
  }

  struct RoleStatus {
    address account;
    bool paused;
  }

  function finalizeDaiDeposit(
    address smartWallet, address initialUserSigningKey, uint256 daiAmount
  ) external;

  function finalizeDharmaDaiDeposit(
    address smartWallet, address initialUserSigningKey, uint256 dDaiAmount
  ) external;

  function mint(uint256 daiAmount) external returns (uint256 dDaiMinted);
  
  function redeem(uint256 dDaiAmount) external returns (uint256 daiReceived);
  
  function tradeDDaiForUSDC(
    uint256 daiEquivalentAmount,
    uint256 quotedDaiToUSDCExchangeRate
  ) external returns (uint256 usdcReceived);
  
  function tradeUSDCForDDai(
    uint256 usdcAmount,
    uint256 quotedUSDCToDaiExchangeRate
  ) external returns (uint256 dDaiMinted);

  function withdrawUSDC(address recipient, uint256 usdcAmount) external;

  function withdrawDai(address recipient, uint256 daiAmount) external;

  function withdrawDharmaDai(address recipient, uint256 dDaiAmount) external;

  function withdraw(
    ERC20Interface token, address recipient, uint256 amount
  ) external returns (bool success);

  function call(
    address payable target, uint256 amount, bytes calldata data
  ) external returns (bool ok, bytes memory returnData);
  
  function setLimit(uint256 daiAmount) 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 isDharmaSmartWallet(
    address smartWallet, address initialUserSigningKey
  ) external view returns (bool dharmaSmartWallet);

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

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

  function getPauser() external view returns (address pauser);
  
  function getReserves() external view returns (
    uint256 dai, uint256 dDai, uint256 dDaiUnderlying
  );
  
  function getLimit() external view returns (
    uint256 daiAmount, uint256 dDaiAmount
  );
}

interface ERC20Interface {
  function balanceOf(address) external view returns (uint256);
  function approve(address, uint256) external returns (bool);
  function transfer(address, uint256) external returns (bool);
}

interface DTokenInterface {
  function mint(uint256 underlyingToSupply) external returns (uint256 dTokensMinted);
  function redeem(uint256 dTokensToBurn) external returns (uint256 underlyingReceived);
  function redeemUnderlying(uint256 underlyingToReceive) external returns (uint256 dTokensBurned);
  function balanceOf(address) external view returns (uint256);
  function balanceOfUnderlying(address) external view returns (uint256);
  function transfer(address, uint256) external returns (bool);
  function approve(address, uint256) external returns (bool);
  function exchangeRateCurrent() external view returns (uint256);
}

interface TradeHelperInterface {
  function tradeUSDCForDDai(uint256 amountUSDC, uint256 quotedExchangeRate) external returns (uint256 dDaiMinted);
  function tradeDDaiForUSDC(uint256 amountDai, uint256 quotedExchangeRate) external returns (uint256 usdcReceived);
  function getExchangeRateAndExpectedDai(uint256 usdc) external view returns (uint256 exchangeRate, uint256 exchangeRateUnderlying, uint256 dai);
  function getExchangeRateAndExpectedUSDC(uint256 dai) external view returns (uint256 exchangeRate, uint256 exchangeRateUnderlying, uint256 usdc);
}


library SafeMath {
  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");
    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 {
  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );

  address private _owner;

  address private _newPotentialOwner;

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

  /**
   * @dev Allows a new account (`newOwner`) to accept ownership.
   * Can only be called by the current owner.
   */
  function transferOwnership(address newOwner) external 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() external 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() external {
    require(
      msg.sender == _newPotentialOwner,
      "TwoStepOwnable: current owner must set caller as new potential owner."
    );

    delete _newPotentialOwner;

    emit OwnershipTransferred(_owner, msg.sender);

    _owner = msg.sender;
  }

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

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

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


/**
 * @title DharmaReserveManagerV2 (staging version)
 * @author 0age
 * @notice This contract is owned by the Dharma Reserve Manager multisig and
 * manages Dharma's reserves. It designates a collection 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:
 *  - depositManager (0): initiates token transfers to smart wallets
 *  - adjuster (1): mints / redeems Dai, and swaps USDC, for dDai
 *  - pauser (2): pauses any role (only the owner is then able to unpause it)
 *
 * When finalizing deposits, the deposit manager must adhere to two constraints:
 *  - it must provide "proof" that the recipient is a smart wallet by including
 *    the initial user signing key used to derive the smart wallet address
 *  - it must not attempt to transfer more Dai, or more than the Dai-equivalent
 *    value of Dharma Dai, than the current "limit" set by the owner.
 *
 * Reserves can be retrieved via `getReserves`, the current limit can be
 * retrieved via `getLimit`, and "proofs" can be validated via `isSmartWallet`.
 */
contract DharmaReserveManagerV2Staging is
  DharmaReserveManagerV2Interface,
  TwoStepOwnable {
  using SafeMath for uint256;

  // Maintain a role status mapping with assigned accounts and paused states.
  mapping(uint256 => RoleStatus) private _roles;
  
  // Maintain a maximum allowable transfer size (in Dai) for the deposit manager.
  uint256 private _limit;

  // This contract interacts with USDC, Dai, and Dharma Dai.
  ERC20Interface internal constant _USDC = ERC20Interface(
    0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 // mainnet
  );

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

  DTokenInterface internal constant _DDAI = DTokenInterface(
    0x00000000001876eB1444c986fD502e618c587430
  );
  
  TradeHelperInterface internal constant _TRADE_HELPER = TradeHelperInterface(
    0xb5f23a203F02D2e595BBC96F5a499814CD8cA186
  );

  // The "Create2 Header" is used to compute smart wallet deployment addresses.
  bytes21 internal constant _CREATE2_HEADER = bytes21(
    0xff8D1e00b000e56d5BcB006F3a008Ca6003b9F0033 // control character + factory
  );
  
  // The "Wallet creation code" header & footer are also used to derive wallets.
  bytes internal constant _WALLET_CREATION_CODE_HEADER = hex"60806040526040516104423803806104428339818101604052602081101561002657600080fd5b810190808051604051939291908464010000000082111561004657600080fd5b90830190602082018581111561005b57600080fd5b825164010000000081118282018810171561007557600080fd5b82525081516020918201929091019080838360005b838110156100a257818101518382015260200161008a565b50505050905090810190601f1680156100cf5780820380516001836020036101000a031916815260200191505b5060405250505060006100e661019e60201b60201c565b6001600160a01b0316826040518082805190602001908083835b6020831061011f5780518252601f199092019160209182019101610100565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461017f576040519150601f19603f3d011682016040523d82523d6000602084013e610184565b606091505b5050905080610197573d6000803e3d6000fd5b50506102be565b60405160009081906060906eb45d6593312ac9fde193f3d06336449083818181855afa9150503d80600081146101f0576040519150601f19603f3d011682016040523d82523d6000602084013e6101f5565b606091505b509150915081819061029f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561026457818101518382015260200161024c565b50505050905090810190601f1680156102915780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508080602001905160208110156102b557600080fd5b50519392505050565b610175806102cd6000396000f3fe608060405261001461000f610016565b61011c565b005b60405160009081906060906eb45d6593312ac9fde193f3d06336449083818181855afa9150503d8060008114610068576040519150601f19603f3d011682016040523d82523d6000602084013e61006d565b606091505b50915091508181906100fd5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156100c25781810151838201526020016100aa565b50505050905090810190601f1680156100ef5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5080806020019051602081101561011357600080fd5b50519392505050565b3660008037600080366000845af43d6000803e80801561013b573d6000f35b3d6000fdfea265627a7a723158203c578cc1552f1d1b48134a72934fe12fb89a29ff396bd514b9a4cebcacc5cacc64736f6c634300050b003200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000";
  bytes28 internal constant _WALLET_CREATION_CODE_FOOTER = bytes28(
    0x00000000000000000000000000000000000000000000000000000000
  );

  /**
   * @notice In the constructor, set the initial owner to the transaction
   * submitter and initial minimum timelock interval and default timelock
   * expiration values.
   */
  constructor() public {
    // Call Dai to set an allowance for Dharma Dai in order to mint dDai.
    require(_DAI.approve(address(_DDAI), uint256(-1)));
    
    // Call USDC to set an allowance for the trade helper contract.
    require(_USDC.approve(address(_TRADE_HELPER), uint256(-1)));
  
    // Call dDai to set an allowance for the trade helper contract.
    require(_DDAI.approve(address(_TRADE_HELPER), uint256(-1)));  
    
    // Set the initial limit to 300 Dai.
    _limit = 300 * 1e18;
  }

  /**
   * @notice Transfer `daiAmount` Dai to `smartWallet`, providing the initial
   * user signing key `initialUserSigningKey` as proof that the specified smart
   * wallet is indeed a Dharma Smart Wallet - this assumes that the address is
   * derived and deployed using the Dharma Smart Wallet Factory V1. In addition,
   * the specified amount must be less than the configured limit amount. Only
   * the owner or the designated deposit manager role may call this function.
   * @param smartWallet address The smart wallet to transfer Dai to.
   * @param initialUserSigningKey address The initial user signing key supplied
   * when deriving the smart wallet address - this could be an EOA or a Dharma
   * key ring address.
   * @param daiAmount uint256 The amount of Dai to transfer - this must be less
   * than the current limit.
   */
  function finalizeDaiDeposit(
    address smartWallet, address initialUserSigningKey, uint256 daiAmount
  ) external onlyOwnerOr(Role.DEPOSIT_MANAGER) {
    // Ensure that the recipient is indeed a smart wallet.
    require(
      _isSmartWallet(smartWallet, initialUserSigningKey),
      "Could not resolve smart wallet using provided signing key."
    );
    
    // Ensure that the amount to transfer is lower than the limit.
    require(daiAmount < _limit, "Transfer size exceeds the limit.");
    
    // Transfer the Dai to the specified smart wallet.
    require(_DAI.transfer(smartWallet, daiAmount), "Dai transfer failed.");
  }

  /**
   * @notice Transfer `dDaiAmount` Dharma Dai to `smartWallet`, providing the
   * initial user signing key `initialUserSigningKey` as proof that the
   * specified smart wallet is indeed a Dharma Smart Wallet - this assumes that
   * the address is derived and deployed using the Dharma Smart Wallet Factory
   * V1. In addition, the Dai equivalent value of the specified dDai amount must
   * be less than the configured limit amount. Only the owner or the designated
   * deposit manager role may call this function.
   * @param smartWallet address The smart wallet to transfer Dai to.
   * @param initialUserSigningKey address The initial user signing key supplied
   * when deriving the smart wallet address - this could be an EOA or a Dharma
   * key ring address.
   * @param dDaiAmount uint256 The amount of Dharma Dai to transfer - the Dai
   * equivalent amount must be less than the current limit.
   */
  function finalizeDharmaDaiDeposit(
    address smartWallet, address initialUserSigningKey, uint256 dDaiAmount
  ) external onlyOwnerOr(Role.DEPOSIT_MANAGER) {
    // Ensure that the recipient is indeed a smart wallet.
    require(
      _isSmartWallet(smartWallet, initialUserSigningKey),
      "Could not resolve smart wallet using provided signing key."
    );
    
    // Get the current dDai exchange rate.
    uint256 exchangeRate = _DDAI.exchangeRateCurrent();

    // Ensure that an exchange rate was actually returned.
    require(exchangeRate != 0, "Could not retrieve dDai exchange rate.");
    
    // Get the equivalent Dai amount of the transfer.
    uint256 daiEquivalent = (dDaiAmount.mul(exchangeRate)) / 1e18;
    
    // Ensure that the amount to transfer is lower than the limit.
    require(daiEquivalent < _limit, "Transfer size exceeds the limit.");

    // Transfer the dDai to the specified smart wallet.
    require(_DDAI.transfer(smartWallet, dDaiAmount), "dDai transfer failed.");
  }

  /**
   * @notice Use `daiAmount` Dai mint Dharma Dai. Only the owner or the
   * designated adjuster role may call this function.
   * @param daiAmount uint256 The amount of Dai to supply when minting Dharma
   * Dai.
   * @return The amount of Dharma Dai minted.
   */
  function mint(
    uint256 daiAmount
  ) external onlyOwnerOr(Role.ADJUSTER) returns (uint256 dDaiMinted) {
    // Use the specified amount of Dai to mint dDai.
    dDaiMinted = _DDAI.mint(daiAmount);
  }

  /**
   * @notice Redeem `dDaiAmount` Dharma Dai for Dai. Only the owner or the
   * designated adjuster role may call this function.
   * @param dDaiAmount uint256 The amount of Dharma Dai to supply when redeeming
   * for Dai.
   * @return The amount of Dai received.
   */ 
  function redeem(
    uint256 dDaiAmount
  ) external onlyOwnerOr(Role.ADJUSTER) returns (uint256 daiReceived) {
    // Redeem the specified amount of dDai for Dai.
    daiReceived = _DDAI.redeem(dDaiAmount);
  }
  
  /**
   * @notice tradeUSDCForDDai `usdcAmount` USDC for Dharma Dai. Only the owner or the
   * designated adjuster role may call this function.
   * @param usdcAmount uint256 The amount of USDC to supply when trading for Dharma Dai.
   * @param quotedUSDCToDaiExchangeRate uint256 The expected DAI/USDC exchange
   * rate, scaled up by 10^18 - this value is returned from the
   * `getExchangeRateAndExpectedDai` view function on the trade helper as
   * `exchangeRate`.
   * @return The amount of dDai received.
   */ 
  function tradeUSDCForDDai(
    uint256 usdcAmount,
    uint256 quotedUSDCToDaiExchangeRate
  ) external onlyOwnerOr(Role.ADJUSTER) returns (uint256 dDaiMinted) {
    dDaiMinted = _TRADE_HELPER.tradeUSDCForDDai(
       usdcAmount, quotedUSDCToDaiExchangeRate
    );
  }

  /**
   * @notice tradeDDaiForUSDC `daiEquivalentAmount` Dai amount to trade in Dharma Dai
   * for USDC. Only the owner or the designated adjuster role may call this function.
   * @param daiEquivalentAmount uint256 The Dai equivalent amount to supply in Dharma
   * Dai when trading for USDC.
   * @param quotedDaiToUSDCExchangeRate uint256 The expected USDC/DAI exchange
   * rate, scaled up by 10^18 - this value is returned from the
   * `getExchangeRateAndExpectedUSDC` view function on the trade helper as
   * `exchangeRate`.
   * @return The amount of USDC received.
   */ 
  function tradeDDaiForUSDC(
    uint256 daiEquivalentAmount,
    uint256 quotedDaiToUSDCExchangeRate
  ) external onlyOwnerOr(Role.ADJUSTER) returns (uint256 usdcReceived) {
    usdcReceived = _TRADE_HELPER.tradeDDaiForUSDC(
       daiEquivalentAmount, quotedDaiToUSDCExchangeRate
    );
  }

  /**
   * @notice Transfer `usdcAmount` USDC to `recipient`. Only the owner may call
   * this function.
   * @param recipient address The account to transfer USDC to.
   * @param usdcAmount uint256 The amount of USDC to transfer.
   */
  function withdrawUSDC(
    address recipient, uint256 usdcAmount
  ) external onlyOwner {
    // Transfer the USDC to the specified recipient.
    require(_USDC.transfer(recipient, usdcAmount), "USDC transfer failed.");
  }

  /**
   * @notice Transfer `daiAmount` Dai to `recipient`. Only the owner may call
   * this function.
   * @param recipient address The account to transfer Dai to.
   * @param daiAmount uint256 The amount of Dai to transfer.
   */
  function withdrawDai(
    address recipient, uint256 daiAmount
  ) external onlyOwner {
    // Transfer the Dai to the specified recipient.
    require(_DAI.transfer(recipient, daiAmount), "Dai transfer failed.");
  }

  /**
   * @notice Transfer `dDaiAmount` Dharma Dai to `recipient`. Only the owner may
   * call this function.
   * @param recipient address The account to transfer Dharma Dai to.
   * @param dDaiAmount uint256 The amount of Dharma Dai to transfer.
   */
  function withdrawDharmaDai(
    address recipient, uint256 dDaiAmount
  ) external onlyOwner {
    // Transfer the dDai to the specified recipient.
    require(_DDAI.transfer(recipient, dDaiAmount), "dDai transfer failed.");
  }

  /**
   * @notice Transfer `amount` of ERC20 token `token` to `recipient`. Only the
   * owner may call this function.
   * @param token ERC20Interface The ERC20 token to transfer.
   * @param recipient address The account to transfer the tokens to.
   * @param amount uint256 The amount of tokens to transfer.
   * @return A boolean to indicate if the transfer was successful - note that
   * unsuccessful ERC20 transfers will usually revert.
   */
  function withdraw(
    ERC20Interface token, address recipient, uint256 amount
  ) external onlyOwner returns (bool success) {
    // Transfer the token to the specified recipient.
    success = token.transfer(recipient, amount);
  }

  /**
   * @notice Call account `target`, supplying value `amount` and data `data`.
   * Only the owner may call this function.
   * @param target address The account to call.
   * @param amount uint256 The amount of ether to include as an endowment.
   * @param data bytes The data to include along with the call.
   * @return A boolean to indicate if the call was successful, as well as the
   * returned data or revert reason.
   */
  function call(
    address payable target, uint256 amount, bytes calldata data
  ) external onlyOwner returns (bool ok, bytes memory returnData) {
    // Call the specified target and supply the specified data.
    (ok, returnData) = target.call.value(amount)(data);
  }

  /**
   * @notice Set `daiAmount` as the new limit on the size of finalized deposits.
   * Only the owner may call this function.
   * @param daiAmount uint256 The new limit on the size of finalized deposits.
   */
  function setLimit(uint256 daiAmount) external onlyOwner {
    // Set the new limit.
    _limit = daiAmount;
  }

  /**
   * @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 deposit manager (0),
   * adjuster (1), and pauser (2).
   */
  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 Unpause 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 deposit manager (0),
   * adjuster (1), and pauser (2).
   */
  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 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
   * deposit manager (0), adjuster (1), and pauser (2).
   * @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 deposit manager (0), adjuster (1), and pauser (2).
   */
  function removeRole(Role role) external onlyOwner {
    _setRole(role, address(0));
  }

  /**
   * @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
   * deposit manager (0), adjuster (1), and pauser (2).
   * @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 deposit manager (0),
   * adjuster (1), and pauser (2).
   * @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 whether a "proof" that a given
   * smart wallet is actually a Dharma Smart Wallet, based on the initial user
   * signing key, is valid or not. This proof only works when the Dharma Smart
   * Wallet in question is derived using V1 of the Dharma Smart Wallet Factory.
   * @param smartWallet address The smart wallet to check.
   * @param initialUserSigningKey address The initial user signing key supplied
   * when deriving the smart wallet address - this could be an EOA or a Dharma
   * key ring address.
   * @return A boolean indicating if the specified smart wallet account is
   * indeed a smart wallet based on the specified initial user signing key.
   */
  function isDharmaSmartWallet(
    address smartWallet, address initialUserSigningKey
  ) external view returns (bool dharmaSmartWallet) {
    dharmaSmartWallet = _isSmartWallet(smartWallet, initialUserSigningKey);
  }

  /**
   * @notice External view function to check the account currently holding the
   * deposit manager role. The deposit manager can process standard deposit
   * finalization via `finalizeDaiDeposit` and `finalizeDharmaDaiDeposit`, but
   * must prove that the recipient is a Dharma Smart Wallet and adhere to the
   * current deposit size limit.
   * @return The address of the current deposit manager, or the null address if
   * none is set.
   */
  function getDepositManager() external view returns (address depositManager) {
    depositManager = _roles[uint256(Role.DEPOSIT_MANAGER)].account;
  }

  /**
   * @notice External view function to check the account currently holding the
   * adjuster role. The adjuster can exchange Dai in reserves for Dharma Dai and
   * vice-versa via minting or redeeming.
   * @return The address of the current adjuster, or the null address if none is
   * set.
   */
  function getAdjuster() external view returns (address adjuster) {
    adjuster = _roles[uint256(Role.ADJUSTER)].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 External view function to check the current reserves held by this
   * contract.
   * @return The Dai and Dharma Dai reserves held by this contract, as well as
   * the Dai-equivalent value of the Dharma Dai reserves.
   */ 
  function getReserves() external view returns (
    uint256 dai, uint256 dDai, uint256 dDaiUnderlying
  ) {
    dai = _DAI.balanceOf(address(this));
    dDai = _DDAI.balanceOf(address(this));
    dDaiUnderlying = _DDAI.balanceOfUnderlying(address(this));
  }

  /**
   * @notice External view function to check the current limit on deposit amount
   * enforced for the deposit manager when finalizing deposits, expressed in Dai
   * and in Dharma Dai.
   * @return The Dai and Dharma Dai limit on deposit finalization amount.
   */  
  function getLimit() external view returns (
    uint256 daiAmount, uint256 dDaiAmount
  ) {
    daiAmount = _limit;
    dDaiAmount = (daiAmount.mul(1e18)).div(_DDAI.exchangeRateCurrent());   
  }

  /**
   * @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
   * deposit manager (0), adjuster (1), and pauser (2).
   * @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 deposit manager (0),
   * adjuster (1), and pauser (2).
   * @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 deposit manager (0),
   * adjuster (1), and pauser (2).
   * @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 Internal pure function to enforce that the given initial user signing
   * key resolves to the given smart wallet when deployed through the Dharma Smart
   * Wallet Factory V1 (staging version).
   * @param smartWallet address The smart wallet.
   * @param initialUserSigningKey address The initial user signing key.
   */
  function _isSmartWallet(
    address smartWallet, address initialUserSigningKey
  ) internal pure returns (bool) {
    // Derive the keccak256 hash of the smart wallet initialization code.
    bytes32 initCodeHash = keccak256(
      abi.encodePacked(
        _WALLET_CREATION_CODE_HEADER,
        initialUserSigningKey,
        _WALLET_CREATION_CODE_FOOTER
      )
    );

    // Attempt to derive a smart wallet address that matches the one provided.
    address target;
    for (uint256 nonce = 0; nonce < 10; nonce++) {
      target = address(          // derive the target deployment address.
        uint160(                 // downcast to match the address type.
          uint256(               // cast to uint to truncate upper digits.
            keccak256(           // compute CREATE2 hash using all inputs.
              abi.encodePacked(  // pack all inputs to the hash together.
                _CREATE2_HEADER, // pass in control character + factory address.
                nonce,           // pass in current nonce as the salt.
                initCodeHash     // pass in hash of contract creation code.
              )
            )
          )
        )
      );

      // Exit early if the provided smart wallet matches derived target address.
      if (target == smartWallet) {
        return true;
      }

      // Otherwise, increment the nonce and derive a new salt.
      nonce++;
    }

    // Explicity recognize no target was found matching provided smart wallet.
    return false;
  }

  /**
   * @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 deposit manager (0), adjuster (1), and pauser (2).
   */
  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

API
[{"constant":true,"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"dai","type":"uint256"},{"internalType":"uint256","name":"dDai","type":"uint256"},{"internalType":"uint256","name":"dDaiUnderlying","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"cancelOwnershipTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"daiAmount","type":"uint256"}],"name":"setLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaReserveManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getDepositManager","outputs":[{"internalType":"address","name":"depositManager","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"},{"internalType":"address","name":"initialUserSigningKey","type":"address"},{"internalType":"uint256","name":"daiAmount","type":"uint256"}],"name":"finalizeDaiDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"usdcAmount","type":"uint256"}],"name":"withdrawUSDC","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"daiAmount","type":"uint256"}],"name":"withdrawDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"usdcAmount","type":"uint256"},{"internalType":"uint256","name":"quotedUSDCToDaiExchangeRate","type":"uint256"}],"name":"tradeUSDCForDDai","outputs":[{"internalType":"uint256","name":"dDaiMinted","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"},{"internalType":"address","name":"initialUserSigningKey","type":"address"}],"name":"isDharmaSmartWallet","outputs":[{"internalType":"bool","name":"dharmaSmartWallet","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"target","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"call","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"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":"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":[],"name":"getAdjuster","outputs":[{"internalType":"address","name":"adjuster","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"daiAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"dDaiMinted","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"dDaiAmount","type":"uint256"}],"name":"withdrawDharmaDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getLimit","outputs":[{"internalType":"uint256","name":"daiAmount","type":"uint256"},{"internalType":"uint256","name":"dDaiAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum DharmaReserveManagerV2Interface.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 DharmaReserveManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"isPaused","outputs":[{"internalType":"bool","name":"paused","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"smartWallet","type":"address"},{"internalType":"address","name":"initialUserSigningKey","type":"address"},{"internalType":"uint256","name":"dDaiAmount","type":"uint256"}],"name":"finalizeDharmaDaiDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"daiEquivalentAmount","type":"uint256"},{"internalType":"uint256","name":"quotedDaiToUSDCExchangeRate","type":"uint256"}],"name":"tradeDDaiForUSDC","outputs":[{"internalType":"uint256","name":"usdcReceived","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract ERC20Interface","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaReserveManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"removeRole","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"dDaiAmount","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"daiReceived","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaReserveManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum DharmaReserveManagerV2Interface.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"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"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":"enum DharmaReserveManagerV2Interface.Role","name":"role","type":"uint8"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"RoleModified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum DharmaReserveManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"RolePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum DharmaReserveManagerV2Interface.Role","name":"role","type":"uint8"}],"name":"RoleUnpaused","type":"event"}]

60806040523480156200001157600080fd5b50600080546001600160a01b03191632178082556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3604080517f095ea7b30000000000000000000000000000000000000000000000000000000081526e1876eb1444c986fd502e618c587430600482015260001960248201529051736b175474e89094c44da98b954eedeac495271d0f9163095ea7b39160448083019260209291908290030181600087803b158015620000df57600080fd5b505af1158015620000f4573d6000803e3d6000fd5b505050506040513d60208110156200010b57600080fd5b50516200011757600080fd5b604080517f095ea7b300000000000000000000000000000000000000000000000000000000815273b5f23a203f02d2e595bbc96f5a499814cd8ca18660048201526000196024820152905173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489163095ea7b39160448083019260209291908290030181600087803b158015620001a057600080fd5b505af1158015620001b5573d6000803e3d6000fd5b505050506040513d6020811015620001cc57600080fd5b5051620001d857600080fd5b604080517f095ea7b300000000000000000000000000000000000000000000000000000000815273b5f23a203f02d2e595bbc96f5a499814cd8ca1866004820152600019602482015290516e1876eb1444c986fd502e618c5874309163095ea7b39160448083019260209291908290030181600087803b1580156200025c57600080fd5b505af115801562000271573d6000803e3d6000fd5b505050506040513d60208110156200028857600080fd5b50516200029457600080fd5b681043561a88293000006003556125c880620002b16000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80638f32d59b11610104578063cf2027bc116100a2578063db006a7511610071578063db006a75146105f3578063edf07f1514610610578063f2e12a3914610630578063f2fde38b1461065f576101cf565b8063cf2027bc14610544578063d1d5a6a71461057a578063d9caed121461059d578063dab41d0d146105d3576101cf565b8063ae8b751f116100de578063ae8b751f146104b7578063b295a00e146104e3578063bb60332014610504578063bc61e73314610524576101cf565b80638f32d59b1461048a5780639badada114610492578063a0712d681461049a576101cf565b806361438a13116101715780636dbf2fa01161014b5780636dbf2fa01461036a5780637008b5481461047257806379ba50971461047a5780638da5cb5b14610482576101cf565b806361438a13146102c7578063693da5bd146102f35780636b30969614610328576101cf565b8063301c7e5d116101ad578063301c7e5d1461022157806331ae1f02146102415780633f9eed321461026557806344471fd91461029b576101cf565b80630902f1ac146101d457806323452b9c146101fa57806327ea6f2b14610204575b600080fd5b6101dc610685565b60408051938452602084019290925282820152519081900360600190f35b61020261080b565b005b6102026004803603602081101561021a57600080fd5b5035610860565b6102026004803603602081101561023757600080fd5b503560ff166108a8565b61024961099b565b604080516001600160a01b039092168252519081900360200190f35b6102026004803603606081101561027b57600080fd5b506001600160a01b038135811691602081013590911690604001356109c1565b610202600480360360408110156102b157600080fd5b506001600160a01b038135169060200135610bd0565b610202600480360360408110156102dd57600080fd5b506001600160a01b038135169060200135610cef565b6103166004803603604081101561030957600080fd5b5080359060200135610e09565b60408051918252519081900360200190f35b6103566004803603604081101561033e57600080fd5b506001600160a01b0381358116916020013516610f31565b604080519115158252519081900360200190f35b6103ef6004803603606081101561038057600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156103b057600080fd5b8201836020820111156103c257600080fd5b803590602001918460018302840111640100000000831117156103e457600080fd5b509092509050610f44565b604051808315151515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561043657818101518382015260200161041e565b50505050905090810190601f1680156104635780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b610249610ffc565b610202611007565b6102496110ac565b6103566110bb565b6102496110cc565b610316600480360360208110156104b057600080fd5b50356110d8565b610202600480360360408110156104cd57600080fd5b506001600160a01b0381351690602001356111f9565b6104eb61130f565b6040805192835260208301919091528051918290030190f35b6103566004803603602081101561051a57600080fd5b503560ff166113b8565b6103566004803603602081101561053a57600080fd5b503560ff166113c9565b6102026004803603606081101561055a57600080fd5b506001600160a01b038135811691602081013590911690604001356113d4565b6103166004803603604081101561059057600080fd5b50803590602001356116ba565b610356600480360360608110156105b357600080fd5b506001600160a01b038135811691602081013590911690604001356117ae565b610202600480360360208110156105e957600080fd5b503560ff16611853565b6103166004803603602081101561060957600080fd5b50356118a4565b6102026004803603602081101561062657600080fd5b503560ff16611992565b6102026004803603604081101561064657600080fd5b50803560ff1690602001356001600160a01b0316611ae1565b6102026004803603602081101561067557600080fd5b50356001600160a01b0316611b89565b604080516370a0823160e01b8152306004820152905160009182918291736b175474e89094c44da98b954eedeac495271d0f916370a0823191602480820192602092909190829003018186803b1580156106de57600080fd5b505afa1580156106f2573d6000803e3d6000fd5b505050506040513d602081101561070857600080fd5b5051604080516370a0823160e01b815230600482015290519194506e1876eb1444c986fd502e618c587430916370a0823191602480820192602092909190829003018186803b15801561075a57600080fd5b505afa15801561076e573d6000803e3d6000fd5b505050506040513d602081101561078457600080fd5b505160408051633af9e66960e01b815230600482015290519193506e1876eb1444c986fd502e618c58743091633af9e66991602480820192602092909190829003018186803b1580156107d657600080fd5b505afa1580156107ea573d6000803e3d6000fd5b505050506040513d602081101561080057600080fd5b505192939192919050565b6108136110bb565b61084e5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b600180546001600160a01b0319169055565b6108686110bb565b6108a35760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b600355565b6108b06110bb565b6108eb5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6000600260008360028111156108fd57fe5b815260208101919091526040016000208054909150600160a01b900460ff166109575760405162461bcd60e51b81526004018080602001828103825260258152602001806120376025913960400191505060405180910390fd5b805460ff60a01b1916815581600281111561096e57fe5b6040517fd9ff16dcccc040d408ddf47191ae2d5313510993b245b3a7ccfb0258a4401d7890600090a25050565b6000600281805b81526020810191909152604001600020546001600160a01b0316919050565b60006109cb6110bb565b610a58576109d881611c33565b610a135760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b610a1c81611c67565b15610a585760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b610a628484611c9a565b610a9d5760405162461bcd60e51b815260040180806020018281038252603a815260200180611f4a603a913960400191505060405180910390fd5b6003548210610af3576040805162461bcd60e51b815260206004820181905260248201527f5472616e736665722073697a65206578636565647320746865206c696d69742e604482015290519081900360640190fd5b6040805163a9059cbb60e01b81526001600160a01b0386166004820152602481018490529051736b175474e89094c44da98b954eedeac495271d0f9163a9059cbb9160448083019260209291908290030181600087803b158015610b5657600080fd5b505af1158015610b6a573d6000803e3d6000fd5b505050506040513d6020811015610b8057600080fd5b5051610bca576040805162461bcd60e51b81526020600482015260146024820152732230b4903a3930b739b332b9103330b4b632b21760611b604482015290519081900360640190fd5b50505050565b610bd86110bb565b610c135760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6040805163a9059cbb60e01b81526001600160a01b038416600482015260248101839052905173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489163a9059cbb9160448083019260209291908290030181600087803b158015610c7657600080fd5b505af1158015610c8a573d6000803e3d6000fd5b505050506040513d6020811015610ca057600080fd5b5051610ceb576040805162461bcd60e51b81526020600482015260156024820152742aa9a221903a3930b739b332b9103330b4b632b21760591b604482015290519081900360640190fd5b5050565b610cf76110bb565b610d325760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6040805163a9059cbb60e01b81526001600160a01b0384166004820152602481018390529051736b175474e89094c44da98b954eedeac495271d0f9163a9059cbb9160448083019260209291908290030181600087803b158015610d9557600080fd5b505af1158015610da9573d6000803e3d6000fd5b505050506040513d6020811015610dbf57600080fd5b5051610ceb576040805162461bcd60e51b81526020600482015260146024820152732230b4903a3930b739b332b9103330b4b632b21760611b604482015290519081900360640190fd5b60006001610e156110bb565b610ea257610e2281611c33565b610e5d5760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b610e6681611c67565b15610ea25760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6040805163693da5bd60e01b81526004810186905260248101859052905173b5f23a203f02d2e595bbc96f5a499814cd8ca1869163693da5bd9160448083019260209291908290030181600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b5051949350505050565b6000610f3d8383611c9a565b9392505050565b60006060610f506110bb565b610f8b5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b856001600160a01b0316858585604051808383808284376040519201945060009350909150508083038185875af1925050503d8060008114610fe9576040519150601f19603f3d011682016040523d82523d6000602084013e610fee565b606091505b509097909650945050505050565b6000600281816109a2565b6001546001600160a01b031633146110505760405162461bcd60e51b8152600401808060200182810382526045815260200180611fa96045913960600191505060405180910390fd5b600180546001600160a01b03191690556000805460405133926001600160a01b03909216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03191633179055565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600060028160016109a2565b600060016110e46110bb565b611171576110f181611c33565b61112c5760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61113581611c67565b156111715760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6e1876eb1444c986fd502e618c5874306001600160a01b031663a0712d68846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156111c657600080fd5b505af11580156111da573d6000803e3d6000fd5b505050506040513d60208110156111f057600080fd5b50519392505050565b6112016110bb565b61123c5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6040805163a9059cbb60e01b81526001600160a01b03841660048201526024810183905290516e1876eb1444c986fd502e618c5874309163a9059cbb9160448083019260209291908290030181600087803b15801561129a57600080fd5b505af11580156112ae573d6000803e3d6000fd5b505050506040513d60208110156112c457600080fd5b5051610ceb576040805162461bcd60e51b8152602060048201526015602482015274322230b4903a3930b739b332b9103330b4b632b21760591b604482015290519081900360640190fd5b60008060035491506113b26e1876eb1444c986fd502e618c5874306001600160a01b031663bd6d894d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561136257600080fd5b505afa158015611376573d6000803e3d6000fd5b505050506040513d602081101561138c57600080fd5b50516113a684670de0b6b3a764000063ffffffff611de916565b9063ffffffff611e4216565b90509091565b60006113c382611c33565b92915050565b60006113c382611c67565b60006113de6110bb565b61146b576113eb81611c33565b6114265760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61142f81611c67565b1561146b5760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6114758484611c9a565b6114b05760405162461bcd60e51b815260040180806020018281038252603a815260200180611f4a603a913960400191505060405180910390fd5b60006e1876eb1444c986fd502e618c5874306001600160a01b031663bd6d894d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114fa57600080fd5b505afa15801561150e573d6000803e3d6000fd5b505050506040513d602081101561152457600080fd5b50519050806115645760405162461bcd60e51b81526004018080602001828103825260268152602001806120dc6026913960400191505060405180910390fd5b6000670de0b6b3a764000061157f858463ffffffff611de916565b8161158657fe5b04905060035481106115df576040805162461bcd60e51b815260206004820181905260248201527f5472616e736665722073697a65206578636565647320746865206c696d69742e604482015290519081900360640190fd5b6040805163a9059cbb60e01b81526001600160a01b03881660048201526024810186905290516e1876eb1444c986fd502e618c5874309163a9059cbb9160448083019260209291908290030181600087803b15801561163d57600080fd5b505af1158015611651573d6000803e3d6000fd5b505050506040513d602081101561166757600080fd5b50516116b2576040805162461bcd60e51b8152602060048201526015602482015274322230b4903a3930b739b332b9103330b4b632b21760591b604482015290519081900360640190fd5b505050505050565b600060016116c66110bb565b611753576116d381611c33565b61170e5760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61171781611c67565b156117535760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6040805163d1d5a6a760e01b81526004810186905260248101859052905173b5f23a203f02d2e595bbc96f5a499814cd8ca1869163d1d5a6a79160448083019260209291908290030181600087803b158015610efd57600080fd5b60006117b86110bb565b6117f35760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b836001600160a01b031663a9059cbb84846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610efd57600080fd5b61185b6110bb565b6118965760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6118a1816000611ea9565b50565b600060016118b06110bb565b61193d576118bd81611c33565b6118f85760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61190181611c67565b1561193d5760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6e1876eb1444c986fd502e618c5874306001600160a01b031663db006a75846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156111c657600080fd5b600261199c6110bb565b611a29576119a981611c33565b6119e45760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b6119ed81611c67565b15611a295760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b600060026000846002811115611a3b57fe5b815260208101919091526040016000208054909150600160a01b900460ff1615611a965760405162461bcd60e51b81526004018080602001828103825260238152602001806120816023913960400191505060405180910390fd5b805460ff60a01b1916600160a01b178155826002811115611ab357fe5b6040517fad75709c5a2559beeed6c59693a5ea8701185d51947d3eef38713bb0fe5891e990600090a2505050565b611ae96110bb565b611b245760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6001600160a01b038116611b7f576040805162461bcd60e51b815260206004820152601760248201527f4d75737420737570706c7920616e206163636f756e742e000000000000000000604482015290519081900360640190fd5b610ceb8282611ea9565b611b916110bb565b611bcc5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6001600160a01b038116611c115760405162461bcd60e51b81526004018080602001828103825260388152602001806120a46038913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600060026000836002811115611c4557fe5b81526020810191909152604001600020546001600160a01b0316331492915050565b600060026000836002811115611c7957fe5b8152602081019190915260400160002054600160a01b900460ff1692915050565b600080604051806104c001604052806104928152602001612102610492913983600060201b6040516020018084805190602001908083835b60208310611cf15780518252601f199092019160209182019101611cd2565b51815160209384036101000a600019018019909216911617905260609690961b6bffffffffffffffffffffffff191692019182525063ffffffff1992909216601483015250604080518083036010018152603090920190528051910120915060009050805b600a811015611ddd57604080517fff8d1e00b000e56d5bcb006f3a008ca6003b9f00330000000000000000000000602080830191909152603582018490526055808301879052835180840390910181526075909201909252805191012091506001600160a01b038083169087161415611dd557600193505050506113c3565b600201611d56565b50600095945050505050565b600082611df8575060006113c3565b82820282848281611e0557fe5b0414610f3d5760405162461bcd60e51b81526004018080602001828103825260218152602001806120166021913960400191505060405180910390fd5b6000808211611e98576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611ea157fe5b049392505050565b600060026000846002811115611ebb57fe5b8152602081019190915260400160002080549091506001600160a01b03838116911614611f445780546001600160a01b0319166001600160a01b038316178155826002811115611f0757fe5b604080516001600160a01b038516815290517f40ab465936efb8324cf37e3a29170c60d9b81de43af89693ce9d92c761e42adc9181900360200190a25b50505056fe436f756c64206e6f74207265736f6c766520736d6172742077616c6c6574207573696e672070726f7669646564207369676e696e67206b65792e43616c6c657220646f6573206e6f742068617665206120726571756972656420726f6c652e54776f537465704f776e61626c653a2063757272656e74206f776e6572206d757374207365742063616c6c6572206173206e657720706f74656e7469616c206f776e65722e54776f537465704f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65722e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f6c6520696e207175657374696f6e20697320616c726561647920756e7061757365642e526f6c6520696e207175657374696f6e2069732063757272656e746c79207061757365642e526f6c6520696e207175657374696f6e20697320616c7265616479207061757365642e54776f537465704f776e61626c653a206e657720706f74656e7469616c206f776e657220697320746865207a65726f20616464726573732e436f756c64206e6f7420726574726965766520644461692065786368616e676520726174652e60806040526040516104423803806104428339818101604052602081101561002657600080fd5b810190808051604051939291908464010000000082111561004657600080fd5b90830190602082018581111561005b57600080fd5b825164010000000081118282018810171561007557600080fd5b82525081516020918201929091019080838360005b838110156100a257818101518382015260200161008a565b50505050905090810190601f1680156100cf5780820380516001836020036101000a031916815260200191505b5060405250505060006100e661019e60201b60201c565b6001600160a01b0316826040518082805190602001908083835b6020831061011f5780518252601f199092019160209182019101610100565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461017f576040519150601f19603f3d011682016040523d82523d6000602084013e610184565b606091505b5050905080610197573d6000803e3d6000fd5b50506102be565b60405160009081906060906eb45d6593312ac9fde193f3d06336449083818181855afa9150503d80600081146101f0576040519150601f19603f3d011682016040523d82523d6000602084013e6101f5565b606091505b509150915081819061029f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561026457818101518382015260200161024c565b50505050905090810190601f1680156102915780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508080602001905160208110156102b557600080fd5b50519392505050565b610175806102cd6000396000f3fe608060405261001461000f610016565b61011c565b005b60405160009081906060906eb45d6593312ac9fde193f3d06336449083818181855afa9150503d8060008114610068576040519150601f19603f3d011682016040523d82523d6000602084013e61006d565b606091505b50915091508181906100fd5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156100c25781810151838201526020016100aa565b50505050905090810190601f1680156100ef5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5080806020019051602081101561011357600080fd5b50519392505050565b3660008037600080366000845af43d6000803e80801561013b573d6000f35b3d6000fdfea265627a7a723158203c578cc1552f1d1b48134a72934fe12fb89a29ff396bd514b9a4cebcacc5cacc64736f6c634300050b003200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000a265627a7a72315820d23c0db4b4bd6338aebd0cd821222a2a7909deb79c36d337245c23eb723d756b64736f6c634300050b0032

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80638f32d59b11610104578063cf2027bc116100a2578063db006a7511610071578063db006a75146105f3578063edf07f1514610610578063f2e12a3914610630578063f2fde38b1461065f576101cf565b8063cf2027bc14610544578063d1d5a6a71461057a578063d9caed121461059d578063dab41d0d146105d3576101cf565b8063ae8b751f116100de578063ae8b751f146104b7578063b295a00e146104e3578063bb60332014610504578063bc61e73314610524576101cf565b80638f32d59b1461048a5780639badada114610492578063a0712d681461049a576101cf565b806361438a13116101715780636dbf2fa01161014b5780636dbf2fa01461036a5780637008b5481461047257806379ba50971461047a5780638da5cb5b14610482576101cf565b806361438a13146102c7578063693da5bd146102f35780636b30969614610328576101cf565b8063301c7e5d116101ad578063301c7e5d1461022157806331ae1f02146102415780633f9eed321461026557806344471fd91461029b576101cf565b80630902f1ac146101d457806323452b9c146101fa57806327ea6f2b14610204575b600080fd5b6101dc610685565b60408051938452602084019290925282820152519081900360600190f35b61020261080b565b005b6102026004803603602081101561021a57600080fd5b5035610860565b6102026004803603602081101561023757600080fd5b503560ff166108a8565b61024961099b565b604080516001600160a01b039092168252519081900360200190f35b6102026004803603606081101561027b57600080fd5b506001600160a01b038135811691602081013590911690604001356109c1565b610202600480360360408110156102b157600080fd5b506001600160a01b038135169060200135610bd0565b610202600480360360408110156102dd57600080fd5b506001600160a01b038135169060200135610cef565b6103166004803603604081101561030957600080fd5b5080359060200135610e09565b60408051918252519081900360200190f35b6103566004803603604081101561033e57600080fd5b506001600160a01b0381358116916020013516610f31565b604080519115158252519081900360200190f35b6103ef6004803603606081101561038057600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156103b057600080fd5b8201836020820111156103c257600080fd5b803590602001918460018302840111640100000000831117156103e457600080fd5b509092509050610f44565b604051808315151515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561043657818101518382015260200161041e565b50505050905090810190601f1680156104635780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b610249610ffc565b610202611007565b6102496110ac565b6103566110bb565b6102496110cc565b610316600480360360208110156104b057600080fd5b50356110d8565b610202600480360360408110156104cd57600080fd5b506001600160a01b0381351690602001356111f9565b6104eb61130f565b6040805192835260208301919091528051918290030190f35b6103566004803603602081101561051a57600080fd5b503560ff166113b8565b6103566004803603602081101561053a57600080fd5b503560ff166113c9565b6102026004803603606081101561055a57600080fd5b506001600160a01b038135811691602081013590911690604001356113d4565b6103166004803603604081101561059057600080fd5b50803590602001356116ba565b610356600480360360608110156105b357600080fd5b506001600160a01b038135811691602081013590911690604001356117ae565b610202600480360360208110156105e957600080fd5b503560ff16611853565b6103166004803603602081101561060957600080fd5b50356118a4565b6102026004803603602081101561062657600080fd5b503560ff16611992565b6102026004803603604081101561064657600080fd5b50803560ff1690602001356001600160a01b0316611ae1565b6102026004803603602081101561067557600080fd5b50356001600160a01b0316611b89565b604080516370a0823160e01b8152306004820152905160009182918291736b175474e89094c44da98b954eedeac495271d0f916370a0823191602480820192602092909190829003018186803b1580156106de57600080fd5b505afa1580156106f2573d6000803e3d6000fd5b505050506040513d602081101561070857600080fd5b5051604080516370a0823160e01b815230600482015290519194506e1876eb1444c986fd502e618c587430916370a0823191602480820192602092909190829003018186803b15801561075a57600080fd5b505afa15801561076e573d6000803e3d6000fd5b505050506040513d602081101561078457600080fd5b505160408051633af9e66960e01b815230600482015290519193506e1876eb1444c986fd502e618c58743091633af9e66991602480820192602092909190829003018186803b1580156107d657600080fd5b505afa1580156107ea573d6000803e3d6000fd5b505050506040513d602081101561080057600080fd5b505192939192919050565b6108136110bb565b61084e5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b600180546001600160a01b0319169055565b6108686110bb565b6108a35760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b600355565b6108b06110bb565b6108eb5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6000600260008360028111156108fd57fe5b815260208101919091526040016000208054909150600160a01b900460ff166109575760405162461bcd60e51b81526004018080602001828103825260258152602001806120376025913960400191505060405180910390fd5b805460ff60a01b1916815581600281111561096e57fe5b6040517fd9ff16dcccc040d408ddf47191ae2d5313510993b245b3a7ccfb0258a4401d7890600090a25050565b6000600281805b81526020810191909152604001600020546001600160a01b0316919050565b60006109cb6110bb565b610a58576109d881611c33565b610a135760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b610a1c81611c67565b15610a585760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b610a628484611c9a565b610a9d5760405162461bcd60e51b815260040180806020018281038252603a815260200180611f4a603a913960400191505060405180910390fd5b6003548210610af3576040805162461bcd60e51b815260206004820181905260248201527f5472616e736665722073697a65206578636565647320746865206c696d69742e604482015290519081900360640190fd5b6040805163a9059cbb60e01b81526001600160a01b0386166004820152602481018490529051736b175474e89094c44da98b954eedeac495271d0f9163a9059cbb9160448083019260209291908290030181600087803b158015610b5657600080fd5b505af1158015610b6a573d6000803e3d6000fd5b505050506040513d6020811015610b8057600080fd5b5051610bca576040805162461bcd60e51b81526020600482015260146024820152732230b4903a3930b739b332b9103330b4b632b21760611b604482015290519081900360640190fd5b50505050565b610bd86110bb565b610c135760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6040805163a9059cbb60e01b81526001600160a01b038416600482015260248101839052905173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489163a9059cbb9160448083019260209291908290030181600087803b158015610c7657600080fd5b505af1158015610c8a573d6000803e3d6000fd5b505050506040513d6020811015610ca057600080fd5b5051610ceb576040805162461bcd60e51b81526020600482015260156024820152742aa9a221903a3930b739b332b9103330b4b632b21760591b604482015290519081900360640190fd5b5050565b610cf76110bb565b610d325760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6040805163a9059cbb60e01b81526001600160a01b0384166004820152602481018390529051736b175474e89094c44da98b954eedeac495271d0f9163a9059cbb9160448083019260209291908290030181600087803b158015610d9557600080fd5b505af1158015610da9573d6000803e3d6000fd5b505050506040513d6020811015610dbf57600080fd5b5051610ceb576040805162461bcd60e51b81526020600482015260146024820152732230b4903a3930b739b332b9103330b4b632b21760611b604482015290519081900360640190fd5b60006001610e156110bb565b610ea257610e2281611c33565b610e5d5760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b610e6681611c67565b15610ea25760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6040805163693da5bd60e01b81526004810186905260248101859052905173b5f23a203f02d2e595bbc96f5a499814cd8ca1869163693da5bd9160448083019260209291908290030181600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b5051949350505050565b6000610f3d8383611c9a565b9392505050565b60006060610f506110bb565b610f8b5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b856001600160a01b0316858585604051808383808284376040519201945060009350909150508083038185875af1925050503d8060008114610fe9576040519150601f19603f3d011682016040523d82523d6000602084013e610fee565b606091505b509097909650945050505050565b6000600281816109a2565b6001546001600160a01b031633146110505760405162461bcd60e51b8152600401808060200182810382526045815260200180611fa96045913960600191505060405180910390fd5b600180546001600160a01b03191690556000805460405133926001600160a01b03909216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03191633179055565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600060028160016109a2565b600060016110e46110bb565b611171576110f181611c33565b61112c5760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61113581611c67565b156111715760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6e1876eb1444c986fd502e618c5874306001600160a01b031663a0712d68846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156111c657600080fd5b505af11580156111da573d6000803e3d6000fd5b505050506040513d60208110156111f057600080fd5b50519392505050565b6112016110bb565b61123c5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6040805163a9059cbb60e01b81526001600160a01b03841660048201526024810183905290516e1876eb1444c986fd502e618c5874309163a9059cbb9160448083019260209291908290030181600087803b15801561129a57600080fd5b505af11580156112ae573d6000803e3d6000fd5b505050506040513d60208110156112c457600080fd5b5051610ceb576040805162461bcd60e51b8152602060048201526015602482015274322230b4903a3930b739b332b9103330b4b632b21760591b604482015290519081900360640190fd5b60008060035491506113b26e1876eb1444c986fd502e618c5874306001600160a01b031663bd6d894d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561136257600080fd5b505afa158015611376573d6000803e3d6000fd5b505050506040513d602081101561138c57600080fd5b50516113a684670de0b6b3a764000063ffffffff611de916565b9063ffffffff611e4216565b90509091565b60006113c382611c33565b92915050565b60006113c382611c67565b60006113de6110bb565b61146b576113eb81611c33565b6114265760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61142f81611c67565b1561146b5760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6114758484611c9a565b6114b05760405162461bcd60e51b815260040180806020018281038252603a815260200180611f4a603a913960400191505060405180910390fd5b60006e1876eb1444c986fd502e618c5874306001600160a01b031663bd6d894d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114fa57600080fd5b505afa15801561150e573d6000803e3d6000fd5b505050506040513d602081101561152457600080fd5b50519050806115645760405162461bcd60e51b81526004018080602001828103825260268152602001806120dc6026913960400191505060405180910390fd5b6000670de0b6b3a764000061157f858463ffffffff611de916565b8161158657fe5b04905060035481106115df576040805162461bcd60e51b815260206004820181905260248201527f5472616e736665722073697a65206578636565647320746865206c696d69742e604482015290519081900360640190fd5b6040805163a9059cbb60e01b81526001600160a01b03881660048201526024810186905290516e1876eb1444c986fd502e618c5874309163a9059cbb9160448083019260209291908290030181600087803b15801561163d57600080fd5b505af1158015611651573d6000803e3d6000fd5b505050506040513d602081101561166757600080fd5b50516116b2576040805162461bcd60e51b8152602060048201526015602482015274322230b4903a3930b739b332b9103330b4b632b21760591b604482015290519081900360640190fd5b505050505050565b600060016116c66110bb565b611753576116d381611c33565b61170e5760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61171781611c67565b156117535760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6040805163d1d5a6a760e01b81526004810186905260248101859052905173b5f23a203f02d2e595bbc96f5a499814cd8ca1869163d1d5a6a79160448083019260209291908290030181600087803b158015610efd57600080fd5b60006117b86110bb565b6117f35760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b836001600160a01b031663a9059cbb84846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610efd57600080fd5b61185b6110bb565b6118965760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6118a1816000611ea9565b50565b600060016118b06110bb565b61193d576118bd81611c33565b6118f85760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b61190181611c67565b1561193d5760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b6e1876eb1444c986fd502e618c5874306001600160a01b031663db006a75846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156111c657600080fd5b600261199c6110bb565b611a29576119a981611c33565b6119e45760405162461bcd60e51b8152600401808060200182810382526025815260200180611f846025913960400191505060405180910390fd5b6119ed81611c67565b15611a295760405162461bcd60e51b815260040180806020018281038252602581526020018061205c6025913960400191505060405180910390fd5b600060026000846002811115611a3b57fe5b815260208101919091526040016000208054909150600160a01b900460ff1615611a965760405162461bcd60e51b81526004018080602001828103825260238152602001806120816023913960400191505060405180910390fd5b805460ff60a01b1916600160a01b178155826002811115611ab357fe5b6040517fad75709c5a2559beeed6c59693a5ea8701185d51947d3eef38713bb0fe5891e990600090a2505050565b611ae96110bb565b611b245760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6001600160a01b038116611b7f576040805162461bcd60e51b815260206004820152601760248201527f4d75737420737570706c7920616e206163636f756e742e000000000000000000604482015290519081900360640190fd5b610ceb8282611ea9565b611b916110bb565b611bcc5760405162461bcd60e51b8152600401808060200182810382526028815260200180611fee6028913960400191505060405180910390fd5b6001600160a01b038116611c115760405162461bcd60e51b81526004018080602001828103825260388152602001806120a46038913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600060026000836002811115611c4557fe5b81526020810191909152604001600020546001600160a01b0316331492915050565b600060026000836002811115611c7957fe5b8152602081019190915260400160002054600160a01b900460ff1692915050565b600080604051806104c001604052806104928152602001612102610492913983600060201b6040516020018084805190602001908083835b60208310611cf15780518252601f199092019160209182019101611cd2565b51815160209384036101000a600019018019909216911617905260609690961b6bffffffffffffffffffffffff191692019182525063ffffffff1992909216601483015250604080518083036010018152603090920190528051910120915060009050805b600a811015611ddd57604080517fff8d1e00b000e56d5bcb006f3a008ca6003b9f00330000000000000000000000602080830191909152603582018490526055808301879052835180840390910181526075909201909252805191012091506001600160a01b038083169087161415611dd557600193505050506113c3565b600201611d56565b50600095945050505050565b600082611df8575060006113c3565b82820282848281611e0557fe5b0414610f3d5760405162461bcd60e51b81526004018080602001828103825260218152602001806120166021913960400191505060405180910390fd5b6000808211611e98576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611ea157fe5b049392505050565b600060026000846002811115611ebb57fe5b8152602081019190915260400160002080549091506001600160a01b03838116911614611f445780546001600160a01b0319166001600160a01b038316178155826002811115611f0757fe5b604080516001600160a01b038516815290517f40ab465936efb8324cf37e3a29170c60d9b81de43af89693ce9d92c761e42adc9181900360200190a25b50505056fe436f756c64206e6f74207265736f6c766520736d6172742077616c6c6574207573696e672070726f7669646564207369676e696e67206b65792e43616c6c657220646f6573206e6f742068617665206120726571756972656420726f6c652e54776f537465704f776e61626c653a2063757272656e74206f776e6572206d757374207365742063616c6c6572206173206e657720706f74656e7469616c206f776e65722e54776f537465704f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65722e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f6c6520696e207175657374696f6e20697320616c726561647920756e7061757365642e526f6c6520696e207175657374696f6e2069732063757272656e746c79207061757365642e526f6c6520696e207175657374696f6e20697320616c7265616479207061757365642e54776f537465704f776e61626c653a206e657720706f74656e7469616c206f776e657220697320746865207a65726f20616464726573732e436f756c64206e6f7420726574726965766520644461692065786368616e676520726174652e60806040526040516104423803806104428339818101604052602081101561002657600080fd5b810190808051604051939291908464010000000082111561004657600080fd5b90830190602082018581111561005b57600080fd5b825164010000000081118282018810171561007557600080fd5b82525081516020918201929091019080838360005b838110156100a257818101518382015260200161008a565b50505050905090810190601f1680156100cf5780820380516001836020036101000a031916815260200191505b5060405250505060006100e661019e60201b60201c565b6001600160a01b0316826040518082805190602001908083835b6020831061011f5780518252601f199092019160209182019101610100565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461017f576040519150601f19603f3d011682016040523d82523d6000602084013e610184565b606091505b5050905080610197573d6000803e3d6000fd5b50506102be565b60405160009081906060906eb45d6593312ac9fde193f3d06336449083818181855afa9150503d80600081146101f0576040519150601f19603f3d011682016040523d82523d6000602084013e6101f5565b606091505b509150915081819061029f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561026457818101518382015260200161024c565b50505050905090810190601f1680156102915780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508080602001905160208110156102b557600080fd5b50519392505050565b610175806102cd6000396000f3fe608060405261001461000f610016565b61011c565b005b60405160009081906060906eb45d6593312ac9fde193f3d06336449083818181855afa9150503d8060008114610068576040519150601f19603f3d011682016040523d82523d6000602084013e61006d565b606091505b50915091508181906100fd5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156100c25781810151838201526020016100aa565b50505050905090810190601f1680156100ef5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5080806020019051602081101561011357600080fd5b50519392505050565b3660008037600080366000845af43d6000803e80801561013b573d6000f35b3d6000fdfea265627a7a723158203c578cc1552f1d1b48134a72934fe12fb89a29ff396bd514b9a4cebcacc5cacc64736f6c634300050b003200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000a265627a7a72315820d23c0db4b4bd6338aebd0cd821222a2a7909deb79c36d337245c23eb723d756b64736f6c634300050b0032

Deployed Bytecode Sourcemap

8029:24775:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8029:24775:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28069:263;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;5820:92;;;:::i;:::-;;21848:114;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21848:114:0;;:::i;22854:267::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22854:267:0;;;;:::i;26665:151::-;;;:::i;:::-;;;;-1:-1:-1;;;;;26665:151:0;;;;;;;;;;;;;;13405:650;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;13405:650:0;;;;;;;;;;;;;;;;;:::i;18995:228::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;18995:228:0;;;;;;;;:::i;19468:222::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;19468:222:0;;;;;;;;:::i;17572:275::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17572:275:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;25974:221;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;25974:221:0;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;21346:275;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;21346:275:0;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;21346:275:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;21346:275: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;-1:-1;21346:275:0;;-1:-1:-1;21346:275:0;-1:-1:-1;21346:275:0;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;21346:275:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27695:118;;;:::i;6070:300::-;;;:::i;6443:75::-;;;:::i;6598:86::-;;;:::i;27134:126::-;;;:::i;16316:209::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16316:209:0;;:::i;19958:233::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;19958:233:0;;;;;;;;:::i;28618:200::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;25138:100;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25138:100:0;;;;:::i;24726:102::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24726:102:0;;;;:::i;14997:1034::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;14997:1034:0;;;;;;;;;;;;;;;;;:::i;18448:297::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18448:297:0;;;;;;;:::i;20657:238::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;20657:238:0;;;;;;;;;;;;;;;;;:::i;24016:89::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24016:89:0;;;;:::i;16816:216::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16816:216:0;;:::i;22320:276::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22320:276:0;;;;:::i;23507:164::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23507:164:0;;;;;;;;-1:-1:-1;;;;;23507:164:0;;:::i;5466:227::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5466:227:0;-1:-1:-1;;;;;5466:227:0;;:::i;28069:263::-;28189:29;;;-1:-1:-1;;;28189:29:0;;28212:4;28189:29;;;;;;28121:11;;;;;;8658:42;;28189:14;;:29;;;;;;;;;;;;;;;8658:42;28189:29;;;5:2:-1;;;;30:1;27;20:12;5:2;28189:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;28189:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28189:29:0;28232:30;;;-1:-1:-1;;;28232:30:0;;28256:4;28232:30;;;;;;28189:29;;-1:-1:-1;8787:42:0;;28232:15;;:30;;;;;28189:29;;28232:30;;;;;;;;8787:42;28232:30;;;5:2:-1;;;;30:1;27;20:12;5:2;28232:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;28232:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28232:30:0;28286:40;;;-1:-1:-1;;;28286:40:0;;28320:4;28286:40;;;;;;28232:30;;-1:-1:-1;8787:42:0;;28286:25;;:40;;;;;28232:30;;28286:40;;;;;;;;8787:42;28286:40;;;5:2:-1;;;;30:1;27;20:12;5:2;28286:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;28286:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28286:40:0;28069:263;;;;28286:40;28069:263;-1:-1:-1;28069:263:0:o;5820:92::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5888:18;5881:25;;-1:-1:-1;;;;;;5881:25:0;;;5820:92::o;21848:114::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21938:6;:18;21848:114::o;22854:267::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22908:35;22946:6;:21;22961:4;22953:13;;;;;;;;22946:21;;;;;;;;;;;-1:-1:-1;22946:21:0;22982:23;;22946:21;;-1:-1:-1;;;;22982:23:0;;;;22974:73;;;;-1:-1:-1;;;22974:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23054:31;;-1:-1:-1;;;;23054:31:0;;;23110:4;23097:18;;;;;;;;;;;;;;;6866:1;22854:267;:::o;26665:151::-;26717:22;26765:6;26717:22;;26772:29;26765:37;;;;;;;;;;;-1:-1:-1;26765:37:0;:45;-1:-1:-1;;;;;26765:45:0;;26665:151;-1:-1:-1;26665:151:0:o;13405:650::-;13535:20;32622:9;:7;:9::i;:::-;32617:171;;32650:13;32658:4;32650:7;:13::i;:::-;32642:63;;;;-1:-1:-1;;;32642:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32723:15;32733:4;32723:9;:15::i;:::-;32722:16;32714:66;;;;-1:-1:-1;;;32714:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13640:50;13655:11;13668:21;13640:14;:50::i;:::-;13624:142;;;;-1:-1:-1;;;13624:142:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13867:6;;13855:9;:18;13847:63;;;;;-1:-1:-1;;;13847:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13987:37;;;-1:-1:-1;;;13987:37:0;;-1:-1:-1;;;;;13987:37:0;;;;;;;;;;;;;;8658:42;;13987:13;;:37;;;;;;;;;;;;;;-1:-1:-1;8658:42:0;13987:37;;;5:2:-1;;;;30:1;27;20:12;5:2;13987:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13987:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13987:37:0;13979:70;;;;;-1:-1:-1;;;13979:70:0;;;;;;;;;;;;-1:-1:-1;;;13979:70:0;;;;;;;;;;;;;;;13405:650;;;;:::o;18995:228::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19154:37;;;-1:-1:-1;;;19154:37:0;;-1:-1:-1;;;;;19154:37:0;;;;;;;;;;;;;;8532:42;;19154:14;;:37;;;;;;;;;;;;;;-1:-1:-1;8532:42:0;19154:37;;;5:2:-1;;;;30:1;27;20:12;5:2;19154:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19154:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19154:37:0;19146:71;;;;;-1:-1:-1;;;19146:71:0;;;;;;;;;;;;-1:-1:-1;;;19146:71:0;;;;;;;;;;;;;;;18995:228;;:::o;19468:222::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19624:35;;;-1:-1:-1;;;19624:35:0;;-1:-1:-1;;;;;19624:35:0;;;;;;;;;;;;;;8658:42;;19624:13;;:35;;;;;;;;;;;;;;-1:-1:-1;8658:42:0;19624:35;;;5:2:-1;;;;30:1;27;20:12;5:2;19624:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19624:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19624:35:0;19616:68;;;;;-1:-1:-1;;;19616:68:0;;;;;;;;;;;;-1:-1:-1;;;19616:68:0;;;;;;;;;;;;;;17572:275;17715:18;17691:13;32622:9;:7;:9::i;:::-;32617:171;;32650:13;32658:4;32650:7;:13::i;:::-;32642:63;;;;-1:-1:-1;;;32642:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32723:15;32733:4;32723:9;:15::i;:::-;32722:16;32714:66;;;;-1:-1:-1;;;32714:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17755:86;;;-1:-1:-1;;;17755:86:0;;;;;;;;;;;;;;;;8925:42;;17755:30;;:86;;;;;;;;;;;;;;-1:-1:-1;8925:42:0;17755:86;;;5:2:-1;;;;30:1;27;20:12;5:2;17755:86:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;17755:86:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17755:86:0;;17572:275;-1:-1:-1;;;;17572:275:0:o;25974:221::-;26088:22;26139:50;26154:11;26167:21;26139:14;:50::i;:::-;26119:70;25974:221;-1:-1:-1;;;25974:221:0:o;21346:275::-;21459:7;21468:23;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21584:6;-1:-1:-1;;;;;21584:11:0;21602:6;21610:4;;21584:31;;;;;30:3:-1;22:6;14;1:33;21584:31:0;;45:16:-1;;;-1:-1;21584:31:0;;-1:-1:-1;21584:31:0;;-1:-1:-1;;21584:31: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;-1:-1;21565:50:0;;;;-1:-1:-1;21346:275:0;-1:-1:-1;;;;;21346:275:0:o;27695:118::-;27739:14;27771:6;27739:14;27771:6;27778:20;;6070:300;6143:18;;-1:-1:-1;;;;;6143:18:0;6129:10;:32;6113:135;;;;-1:-1:-1;;;6113:135:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6264:18;6257:25;;-1:-1:-1;;;;;;6257:25:0;;;-1:-1:-1;6317:6:0;;6296:40;;6325:10;;-1:-1:-1;;;;;6317:6:0;;;;6296:40;;;6345:6;:19;;-1:-1:-1;;;;;;6345:19:0;6354:10;6345:19;;;6070:300::o;6443:75::-;6483:7;6506:6;-1:-1:-1;;;;;6506:6:0;6443:75;:::o;6598:86::-;6638:4;6672:6;-1:-1:-1;;;;;6672:6:0;6658:10;:20;;6598:86::o;27134:126::-;27180:16;27216:6;27180:16;27231:13;27223:22;;16316:209;16404:18;16380:13;32622:9;:7;:9::i;:::-;32617:171;;32650:13;32658:4;32650:7;:13::i;:::-;32642:63;;;;-1:-1:-1;;;32642:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32723:15;32733:4;32723:9;:15::i;:::-;32722:16;32714:66;;;;-1:-1:-1;;;32714:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8787:42;-1:-1:-1;;;;;16498:10:0;;16509:9;16498:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16498:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16498:21:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16498:21:0;;16316:209;-1:-1:-1;;;16316:209:0:o;19958:233::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20122:37;;;-1:-1:-1;;;20122:37:0;;-1:-1:-1;;;;;20122:37:0;;;;;;;;;;;;;;8787:42;;20122:14;;:37;;;;;;;;;;;;;;-1:-1:-1;8787:42:0;20122:37;;;5:2:-1;;;;30:1;27;20:12;5:2;20122:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;20122:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20122:37:0;20114:71;;;;;-1:-1:-1;;;20114:71:0;;;;;;;;;;;;-1:-1:-1;;;20114:71:0;;;;;;;;;;;;;;28618:200;28667:17;28686:18;28729:6;;28717:18;;28755:54;8787:42;-1:-1:-1;;;;;28781:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;28781:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;28781:27:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28781:27:0;28756:19;:9;28770:4;28756:19;:13;:19;:::i;:::-;28755:25;:54;:25;:54;:::i;:::-;28742:67;;28618:200;;:::o;25138:100::-;25188:12;25219:13;25227:4;25219:7;:13::i;:::-;25209:23;25138:100;-1:-1:-1;;25138:100:0:o;24726:102::-;24778:11;24807:15;24817:4;24807:9;:15::i;14997:1034::-;15134:20;32622:9;:7;:9::i;:::-;32617:171;;32650:13;32658:4;32650:7;:13::i;:::-;32642:63;;;;-1:-1:-1;;;32642:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32723:15;32733:4;32723:9;:15::i;:::-;32722:16;32714:66;;;;-1:-1:-1;;;32714:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15239:50;15254:11;15267:21;15239:14;:50::i;:::-;15223:142;;;;-1:-1:-1;;;15223:142:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15422:20;8787:42;-1:-1:-1;;;;;15445:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;15445:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15445:27:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15445:27:0;;-1:-1:-1;15549:17:0;15541:68;;;;-1:-1:-1;;;15541:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15677:21;15734:4;15702:28;:10;15717:12;15702:28;:14;:28;:::i;:::-;15701:37;;;;;;15677:61;;15843:6;;15827:13;:22;15819:67;;;;;-1:-1:-1;;;15819:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15960:39;;;-1:-1:-1;;;15960:39:0;;-1:-1:-1;;;;;15960:39:0;;;;;;;;;;;;;;8787:42;;15960:14;;:39;;;;;;;;;;;;;;-1:-1:-1;8787:42:0;15960:39;;;5:2:-1;;;;30:1;27;20:12;5:2;15960:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15960:39:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15960:39:0;15952:73;;;;;-1:-1:-1;;;15952:73:0;;;;;;;;;;;;-1:-1:-1;;;15952:73:0;;;;;;;;;;;;;;;32794:1;;14997:1034;;;;:::o;18448:297::-;18600:20;18576:13;32622:9;:7;:9::i;:::-;32617:171;;32650:13;32658:4;32650:7;:13::i;:::-;32642:63;;;;-1:-1:-1;;;32642:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32723:15;32733:4;32723:9;:15::i;:::-;32722:16;32714:66;;;;-1:-1:-1;;;32714:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18644:95;;;-1:-1:-1;;;18644:95:0;;;;;;;;;;;;;;;;8925:42;;18644:30;;:95;;;;;;;;;;;;;;-1:-1:-1;8925:42:0;18644:95;;;5:2:-1;;;;30:1;27;20:12;20657:238:0;20770:12;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20856:5;-1:-1:-1;;;;;20856:14:0;;20871:9;20882:6;20856:33;;;;;;;;;;;;;-1:-1:-1;;;;;20856:33:0;-1:-1:-1;;;;;20856:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;24016:89:0;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24073:26;24082:4;24096:1;24073:8;:26::i;:::-;24016:89;:::o;16816:216::-;16907:19;16883:13;32622:9;:7;:9::i;:::-;32617:171;;32650:13;32658:4;32650:7;:13::i;:::-;32642:63;;;;-1:-1:-1;;;32642:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32723:15;32733:4;32723:9;:15::i;:::-;32722:16;32714:66;;;;-1:-1:-1;;;32714:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8787:42;-1:-1:-1;;;;;17002:12:0;;17015:10;17002:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;22320:276:0;22367:11;32622:9;:7;:9::i;:::-;32617:171;;32650:13;32658:4;32650:7;:13::i;:::-;32642:63;;;;-1:-1:-1;;;32642:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32723:15;32733:4;32723:9;:15::i;:::-;32722:16;32714:66;;;;-1:-1:-1;;;32714:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22387:35;22425:6;:21;22440:4;22432:13;;;;;;;;22425:21;;;;;;;;;;;-1:-1:-1;22425:21:0;22462:23;;22425:21;;-1:-1:-1;;;;22462:23:0;;;;22461:24;22453:72;;;;-1:-1:-1;;;22453:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22532:30;;-1:-1:-1;;;;22532:30:0;-1:-1:-1;;;22532:30:0;;;22585:4;22574:16;;;;;;;;;;;;;;;32794:1;22320:276;;:::o;23507:164::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23586:21:0;;23578:57;;;;;-1:-1:-1;;;23578:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;23642:23;23651:4;23657:7;23642:8;:23::i;5466:227::-;6805:9;:7;:9::i;:::-;6797:62;;;;-1:-1:-1;;;6797:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5553:22:0;;5537:112;;;;-1:-1:-1;;;5537:112:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5658:18;:29;;-1:-1:-1;;;;;;5658:29:0;-1:-1:-1;;;;;5658:29:0;;;;;;;;;;5466:227::o;29764:131::-;29815:12;29860:6;:21;29875:4;29867:13;;;;;;;;29860:21;;;;;;;;;;;-1:-1:-1;29860:21:0;:29;-1:-1:-1;;;;;29860:29:0;29846:10;:43;;;-1:-1:-1;;29764:131:0:o;30201:116::-;30254:11;30283:6;:21;30298:4;30290:13;;;;;;;;30283:21;;;;;;;;;;;-1:-1:-1;30283:21:0;:28;-1:-1:-1;;;30283:28:0;;;;;;-1:-1:-1;;30201:116:0:o;30672:1554::-;30781:4;30869:20;30937:28;;;;;;;;;;;;;;;;;30976:21;11765:58;11751:77;;30910:135;;;;;;;;;;;;;;;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;;30910:135:0;;;;;-1:-1:-1;;30910:135:0;;;;;;-1:-1:-1;;;30910:135:0;;;;;;;;-1:-1:-1;30910:135:0;;;26:21:-1;;;22:32;;6:49;;30910:135:0;;;;;;30892:160;;;;;;-1:-1:-1;;;;;31162:958:0;31194:2;31186:5;:10;31162:958;;;31524:307;;;9104:94;31524:307;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;31524:307:0;;;;;;;31446:400;;;;;;-1:-1:-1;;;;;;31976:21:0;;;;;;;31972:59;;;32017:4;32010:11;;;;;;;31972:59;31198:7;;31162:958;;;-1:-1:-1;32215:5:0;;30672:1554;-1:-1:-1;;;;;30672:1554:0:o;4037:202::-;4095:7;4115:6;4111:20;;-1:-1:-1;4130:1:0;4123:8;;4111:20;4150:5;;;4154:1;4150;:5;:1;4170:5;;;;;:10;4162:56;;;;-1:-1:-1;;;4162:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4245:143;4303:7;4331:1;4327;:5;4319:44;;;;;-1:-1:-1;;;4319:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;4381:1;4377;:5;;;;;;;4245:143;-1:-1:-1;;;4245:143:0:o;29186:268::-;29248:35;29286:6;:21;29301:4;29293:13;;;;;;;;29286:21;;;;;;;;;;;-1:-1:-1;29286:21:0;29331:24;;29286:21;;-1:-1:-1;;;;;;29320:35:0;;;29331:24;;29320:35;29316:133;;29366:34;;-1:-1:-1;;;;;;29366:34:0;-1:-1:-1;;;;;29366:34:0;;;;;29427:4;29414:27;;;;;;;;;;;-1:-1:-1;;;;;29414:27:0;;;;;;;;;;;;;;;29316:133;29186:268;;;:::o

Swarm Source

bzzr://d23c0db4b4bd6338aebd0cd821222a2a7909deb79c36d337245c23eb723d756b

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  ]

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.