Contract 0xa96450d3386ece22db20b0ac96ef5684b6d95d53

 

TxHash Block Age From To Value [TxFee]
0xd7a567014334f550def590a5b027955442e78243f83715ec7acc4f696de447f1(pending)22 hrs 25 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN 0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether(Pending)
0x10d7fd05f3ca179a541ee0aaaa37449eeeacb80dce3be114d956595d93c3f63e(pending)22 hrs 25 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN 0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether(Pending)
0x8c88f9c4082f7140c1e74affd0c6221353d48f9174168968956621ccc198ea6c(pending)22 hrs 30 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN 0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether(Pending)
0xed6718e1d9f10860b918d0eb13b99797801b20a0b8ea01842526ccfd58bb89bb72387668 hrs 45 mins ago0x0c9cdf5bbf5227cbcc7e4eacb0cb172a90f4fa48 IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530 Ether0.000167442013
0x3eb315518a3c9f03fb9622f6fbcf34009cdedcdd3d14c39ecd6f97aee2a799a2723639022 hrs 30 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00072944
0x533255ff8dfd2ba96664115881383cf08fc29df33e7512913b6569de7ba9fea0723639022 hrs 30 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00072944
0x1762f96b08fcf1b0b1c1f986ba283e3d0e16d15e1b2672c89e02ed0328d99671723639022 hrs 30 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00072944
0xfaaa8e03db2a3c2f55eb7aace4cfa71fce792422b47e7256536c22cd29f7319d723639022 hrs 30 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.000728416
0x3c436b75d5ca052c2b804798f5840213bee1c121a427f05301d564332454adca723639022 hrs 30 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.0004559
0xaa7fdfa6f924c9890533b5b556ee75b1db8af52db17f1a56c5079346253e3d7e723637122 hrs 36 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00095739
0x59290ae4a713a3882fd8aa6cf0cf77e71952c33da5b9b7a0246e273d28482473723635822 hrs 42 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.0004559
0xf4f899b098f9caa667a8d14c65ea9b971502de460bf2ff05225f5a1e24d3ddbb723635822 hrs 42 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.0004559
0x0631e6d147fb482d947c860f118cdaaefa375845c19ef913d20b55a4995131a0723635222 hrs 44 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00091052
0x69e698fca9b1e349c3d371f96023d14fe8455857216edb9e722952186d52f0c2723635222 hrs 44 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00045526
0xe129f042dfe9d22f3e66b34df9fbf50b52069c4f9cd74e2e95aca866bb1a142c723635022 hrs 45 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.0004559
0x03e472ac517e9c42559b0f6a7f18053d331b4abb834e9844fcb54979ed5f2ab2723634822 hrs 46 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00072944
0x82dcab22701084f1e82e438f3690e57169f7e133c770ab83052431133a4909fa723634622 hrs 46 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.0009118
0xd9b2db3960f5b4cd79d685907bea2ef44612308e0a7d037cbc865f644ffaebe7723634422 hrs 46 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.0009118
0x3e788e912f17656170a919494b3acc00774a8f8a59b21d17e3e0cac9010d5fe4723634422 hrs 46 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00072944
0x5dd8bb986467f8bbfbbe3fbf28c69a3d62609603b98bb3b83b537b9980164a63723634222 hrs 47 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.0004559
0xb627fe39d879a7579caf37cc1abacb10bc4455c0405ef4d3dd68a17415f48457723634222 hrs 47 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00072944
0x2a623a67b321fe19c72f0c6a94e49c7ee06a24266b0a15f3aba48917e17e093a723634022 hrs 47 mins ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.00072944
0x06fb678d46c11f51e2991d55dcce35b74d4ee7edf987bdde15aef80441787df472356071 day 2 hrs ago0xd6f46475ae01a6e8ca0f45d4137f2404ba63ede1 IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530 Ether0.00027907
0x933c9b81dbbc3d32b87c33322767b3b8ac7c9d2e8a3ad7ab1b60a5c722dbad6072355221 day 3 hrs ago0x64874e2f77aa6fc629eed6d6f02c62910e69dc5b IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530.04392 Ether0.000401192
0x0d82580b59fca6fda2dea76f5900e243d35661553c3013be332e1da6f635766672302612 days 9 hrs ago0xfff5ebbd2b21c12d76c619f74b3e441977370072 IN  0xa96450d3386ece22db20b0ac96ef5684b6d95d530 Ether0.000083721
[ Download CSV Export 

Latest 25 Internal Transaction, Click here to view more Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value
0xed6718e1d9f10860b918d0eb13b99797801b20a0b8ea01842526ccfd58bb89bb72387668 hrs 45 mins ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x0c9cdf5bbf5227cbcc7e4eacb0cb172a90f4fa480.08172 Ether
0x06fb678d46c11f51e2991d55dcce35b74d4ee7edf987bdde15aef80441787df472356071 day 2 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xd6f46475ae01a6e8ca0f45d4137f2404ba63ede10.08172 Ether
0x0d82580b59fca6fda2dea76f5900e243d35661553c3013be332e1da6f635766672302612 days 9 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.08172 Ether
0x8eb9f9020562417f48471e0f048c32bf5adba3383ae8a5dd122d905bbe5bc0ad72302612 days 9 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.08172 Ether
0x169f59009d95fcbcaa0c6ae8d4eb4c06defe9cc66eb6a89d797f97f0d3452d5472299082 days 11 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x06550e014dcc6ae4843b574c2ace7dcbdbb9d1d60.01767 Ether
0xe03d1b380875424b49ce2fe9552c67bf732c883426c4398540a172dda236741772295612 days 13 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x9b39e806da554aca2ccdb03e6e7b37ac6369ee7d0.05917 Ether
0x576fdec602fe5f2f8d5cf00e0992b52a9d02fc05d976a81544de116ccbf269fc72295552 days 13 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x9b39e806da554aca2ccdb03e6e7b37ac6369ee7d0.08265 Ether
0xc74165d080437fc59b5e3b1fb35a13aef158d8ddd052c97805c525b2ac484d7272291472 days 15 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x6791eb7c81444e0fc3dd8be2ab605e6dc99071900.08172 Ether
0xe508b7182eb0cde20a3a6edc3887a2c1598baf4e59b0da4d8a1e86e25753140372291472 days 15 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xe8b37de7ca63f6954c37cc62248b4632b4581f810.08172 Ether
0xdd09afd6a05a31041697ef104872113edd07ed4f27c35c9a909649136c0892c772290982 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xa6be6d0bbe99e661d5743f4e58ba40f7af3e273b0.08172 Ether
0xeb9b48d96a770d052c92b9dfa97ceb89d65db22042f18c034844e71649c31f6572287562 days 18 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.08172 Ether
0xb1435e1dc698f43330a7e7f09f2fdb9156147f7c3479af6c6006912b8a9ae3da72252163 days 14 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xb669b9e2613d7c3df3f7e05521dc9721a9a92d100.07491 Ether
0x2f5ab60ca0f7d4280cf1349328e992cd547bfb3528bfbc8c64742565dc10b37b72206374 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x62e8293c080951a97768512bbd85d156531ec3630.02814 Ether
0x2a8cac4d12b8e5b95fe40fe2688f1380cf5c3fd9e1a9198bb8966795427b852572206274 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x62e8293c080951a97768512bbd85d156531ec3630.01689 Ether
0xd46496c890bc7e6e6c5dc5bdb7d237797f9a14a240504e5ef4244e94fbf3cd9c72206204 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.01689 Ether
0xc153a90260667b8f7abb29b4c776aa1066941be5f073914c1d014484b269a22a72206204 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.01689 Ether
0xcd134193e76130d600660c9d7736ca6de32e7e18fb64ebd5ba834644d28f90c272206154 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.01689 Ether
0x42380ac35299f28272252761c456aa41ef77c3f8f7c7c45582a9f9059e67288072206154 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.01689 Ether
0x2411f3ad598d563a241b359b5ea3d6a3f763fed01080f15bf6842ef179ec27d072206074 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.01689 Ether
0xb13db6192c2351415a842e7986cb3337afecc675e7e7171756d1a19120d992a872206014 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.01611 Ether
0xc6b7bcdf1e7d77c4dc382f50b72aeb6b4b1fb31121d1a7b2532d9bb3e96b08d272205954 days 16 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xfff5ebbd2b21c12d76c619f74b3e4419773700720.01767 Ether
0xc7891d5f779fe6b245cb69510436da7b1698d9f5ef247ea04fa066289e88acbf72162465 days 18 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xd0210dc558269a54f772e85a113141c041a8bba10.06481 Ether
0xe5c528b03d297dc455efd77a0688d53eaa53adb36abbe0e77a7ff8895f91d23372154465 days 22 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x1f1d929cf4dbe9b0258f29824053ce354df812280.01149 Ether
0x5c4cb4f61d1f7fab0c45432e9a08168a5422cf5c2353d4a72655bc664ab560d872149276 days 1 hr ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530xd9c8cb73f40985f824f8cf66d4c13bf502bb8c3a0.01676 Ether
0x632ec70df1c12e6625b7046ab55945bad2647d02cd510c566be713027b1e8e7772103647 days 3 hrs ago0xa96450d3386ece22db20b0ac96ef5684b6d95d530x6e525f2b4b2851d91e49d259ef9f60f21d5f5c040.01611 Ether
[ Download CSV Export 
Contract Source Code Verified (Exact Match)
Contract Name: DarknodeRewardVault
Compiler Version: v0.4.25+commit.59dbf8f1
Optimization Enabled: No
Runs (Optimizer):  200


Contract Source Code
pragma solidity ^0.4.25;

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;


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


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  constructor() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to relinquish control of the contract.
   * @notice Renouncing to ownership will leave the contract without an owner.
   * It will not be possible to call the functions with the `onlyOwner`
   * modifier anymore.
   */
  function renounceOwnership() public onlyOwner {
    emit OwnershipRenounced(owner);
    owner = address(0);
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function transferOwnership(address _newOwner) public onlyOwner {
    _transferOwnership(_newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address _newOwner) internal {
    require(_newOwner != address(0));
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }
}

/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * See https://github.com/ethereum/EIPs/issues/179
 */
contract ERC20Basic {
  function totalSupply() public view returns (uint256);
  function balanceOf(address who) public view returns (uint256);
  function transfer(address to, uint256 value) public returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
}

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  function allowance(address owner, address spender)
    public view returns (uint256);

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

  function approve(address spender, uint256 value) public returns (bool);
  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (a == 0) {
      return 0;
    }

    c = a * b;
    assert(c / a == b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    // uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return a / b;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
    c = a + b;
    assert(c >= a);
    return c;
  }
}

/**
 * @title Basic token
 * @dev Basic version of StandardToken, with no allowances.
 */
contract BasicToken is ERC20Basic {
  using SafeMath for uint256;

  mapping(address => uint256) balances;

  uint256 totalSupply_;

  /**
  * @dev Total number of tokens in existence
  */
  function totalSupply() public view returns (uint256) {
    return totalSupply_;
  }

  /**
  * @dev Transfer token for a specified address
  * @param _to The address to transfer to.
  * @param _value The amount to be transferred.
  */
  function transfer(address _to, uint256 _value) public returns (bool) {
    require(_to != address(0));
    require(_value <= balances[msg.sender]);

    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    emit Transfer(msg.sender, _to, _value);
    return true;
  }

  /**
  * @dev Gets the balance of the specified address.
  * @param _owner The address to query the the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  function balanceOf(address _owner) public view returns (uint256) {
    return balances[_owner];
  }

}

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://github.com/ethereum/EIPs/issues/20
 * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract StandardToken is ERC20, BasicToken {

  mapping (address => mapping (address => uint256)) internal allowed;


  /**
   * @dev Transfer tokens from one address to another
   * @param _from address The address which you want to send tokens from
   * @param _to address The address which you want to transfer to
   * @param _value uint256 the amount of tokens to be transferred
   */
  function transferFrom(
    address _from,
    address _to,
    uint256 _value
  )
    public
    returns (bool)
  {
    require(_to != address(0));
    require(_value <= balances[_from]);
    require(_value <= allowed[_from][msg.sender]);

    balances[_from] = balances[_from].sub(_value);
    balances[_to] = balances[_to].add(_value);
    allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
    emit Transfer(_from, _to, _value);
    return true;
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   * Beware that changing an allowance with this method brings the risk that someone may use both the old
   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   * @param _spender The address which will spend the funds.
   * @param _value The amount of tokens to be spent.
   */
  function approve(address _spender, uint256 _value) public returns (bool) {
    allowed[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    return true;
  }

  /**
   * @dev Function to check the amount of tokens that an owner allowed to a spender.
   * @param _owner address The address which owns the funds.
   * @param _spender address The address which will spend the funds.
   * @return A uint256 specifying the amount of tokens still available for the spender.
   */
  function allowance(
    address _owner,
    address _spender
   )
    public
    view
    returns (uint256)
  {
    return allowed[_owner][_spender];
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed[_spender] == 0. To increment
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param _spender The address which will spend the funds.
   * @param _addedValue The amount of tokens to increase the allowance by.
   */
  function increaseApproval(
    address _spender,
    uint256 _addedValue
  )
    public
    returns (bool)
  {
    allowed[msg.sender][_spender] = (
      allowed[msg.sender][_spender].add(_addedValue));
    emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
    return true;
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed[_spender] == 0. To decrement
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param _spender The address which will spend the funds.
   * @param _subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseApproval(
    address _spender,
    uint256 _subtractedValue
  )
    public
    returns (bool)
  {
    uint256 oldValue = allowed[msg.sender][_spender];
    if (_subtractedValue > oldValue) {
      allowed[msg.sender][_spender] = 0;
    } else {
      allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
    }
    emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
    return true;
  }

}

/**
 * @title Pausable
 * @dev Base contract which allows children to implement an emergency stop mechanism.
 */
contract Pausable is Ownable {
  event Pause();
  event Unpause();

  bool public paused = false;


  /**
   * @dev Modifier to make a function callable only when the contract is not paused.
   */
  modifier whenNotPaused() {
    require(!paused);
    _;
  }

  /**
   * @dev Modifier to make a function callable only when the contract is paused.
   */
  modifier whenPaused() {
    require(paused);
    _;
  }

  /**
   * @dev called by the owner to pause, triggers stopped state
   */
  function pause() onlyOwner whenNotPaused public {
    paused = true;
    emit Pause();
  }

  /**
   * @dev called by the owner to unpause, returns to normal state
   */
  function unpause() onlyOwner whenPaused public {
    paused = false;
    emit Unpause();
  }
}

/**
 * @title Pausable token
 * @dev StandardToken modified with pausable transfers.
 **/
contract PausableToken is StandardToken, Pausable {

  function transfer(
    address _to,
    uint256 _value
  )
    public
    whenNotPaused
    returns (bool)
  {
    return super.transfer(_to, _value);
  }

  function transferFrom(
    address _from,
    address _to,
    uint256 _value
  )
    public
    whenNotPaused
    returns (bool)
  {
    return super.transferFrom(_from, _to, _value);
  }

  function approve(
    address _spender,
    uint256 _value
  )
    public
    whenNotPaused
    returns (bool)
  {
    return super.approve(_spender, _value);
  }

  function increaseApproval(
    address _spender,
    uint _addedValue
  )
    public
    whenNotPaused
    returns (bool success)
  {
    return super.increaseApproval(_spender, _addedValue);
  }

  function decreaseApproval(
    address _spender,
    uint _subtractedValue
  )
    public
    whenNotPaused
    returns (bool success)
  {
    return super.decreaseApproval(_spender, _subtractedValue);
  }
}

/**
 * @title Burnable Token
 * @dev Token that can be irreversibly burned (destroyed).
 */
contract BurnableToken is BasicToken {

  event Burn(address indexed burner, uint256 value);

  /**
   * @dev Burns a specific amount of tokens.
   * @param _value The amount of token to be burned.
   */
  function burn(uint256 _value) public {
    _burn(msg.sender, _value);
  }

  function _burn(address _who, uint256 _value) internal {
    require(_value <= balances[_who]);
    // no need to require value <= totalSupply, since that would imply the
    // sender's balance is greater than the totalSupply, which *should* be an assertion failure

    balances[_who] = balances[_who].sub(_value);
    totalSupply_ = totalSupply_.sub(_value);
    emit Burn(_who, _value);
    emit Transfer(_who, address(0), _value);
  }
}

contract RepublicToken is PausableToken, BurnableToken {

    string public constant name = "Republic Token";
    string public constant symbol = "REN";
    uint8 public constant decimals = 18;
    uint256 public constant INITIAL_SUPPLY = 1000000000 * 10**uint256(decimals);

    /// @notice The RepublicToken Constructor.
    constructor() public {
        totalSupply_ = INITIAL_SUPPLY;
        balances[msg.sender] = INITIAL_SUPPLY;
    }

    function transferTokens(address beneficiary, uint256 amount) public onlyOwner returns (bool) {
        /* solium-disable error-reason */
        require(amount > 0);

        balances[owner] = balances[owner].sub(amount);
        balances[beneficiary] = balances[beneficiary].add(amount);
        emit Transfer(owner, beneficiary, amount);

        return true;
    }
}

/**
 * @notice LinkedList is a library for a circular double linked list.
 */
library LinkedList {

    /*
    * @notice A permanent NULL node (0x0) in the circular double linked list.
    * NULL.next is the head, and NULL.previous is the tail.
    */
    address public constant NULL = 0x0;

    /**
    * @notice A node points to the node before it, and the node after it. If
    * node.previous = NULL, then the node is the head of the list. If
    * node.next = NULL, then the node is the tail of the list.
    */
    struct Node {
        bool inList;
        address previous;
        address next;
    }

    /**
    * @notice LinkedList uses a mapping from address to nodes. Each address
    * uniquely identifies a node, and in this way they are used like pointers.
    */
    struct List {
        mapping (address => Node) list;
    }

    /**
    * @notice Insert a new node before an existing node.
    *
    * @param self The list being used.
    * @param target The existing node in the list.
    * @param newNode The next node to insert before the target.
    */
    function insertBefore(List storage self, address target, address newNode) internal {
        require(!isInList(self, newNode), "already in list");
        require(isInList(self, target) || target == NULL, "not in list");

        // It is expected that this value is sometimes NULL.
        address prev = self.list[target].previous;

        self.list[newNode].next = target;
        self.list[newNode].previous = prev;
        self.list[target].previous = newNode;
        self.list[prev].next = newNode;

        self.list[newNode].inList = true;
    }

    /**
    * @notice Insert a new node after an existing node.
    *
    * @param self The list being used.
    * @param target The existing node in the list.
    * @param newNode The next node to insert after the target.
    */
    function insertAfter(List storage self, address target, address newNode) internal {
        require(!isInList(self, newNode), "already in list");
        require(isInList(self, target) || target == NULL, "not in list");

        // It is expected that this value is sometimes NULL.
        address n = self.list[target].next;

        self.list[newNode].previous = target;
        self.list[newNode].next = n;
        self.list[target].next = newNode;
        self.list[n].previous = newNode;

        self.list[newNode].inList = true;
    }

    /**
    * @notice Remove a node from the list, and fix the previous and next
    * pointers that are pointing to the removed node. Removing anode that is not
    * in the list will do nothing.
    *
    * @param self The list being using.
    * @param node The node in the list to be removed.
    */
    function remove(List storage self, address node) internal {
        require(isInList(self, node), "not in list");
        if (node == NULL) {
            return;
        }
        address p = self.list[node].previous;
        address n = self.list[node].next;

        self.list[p].next = n;
        self.list[n].previous = p;

        // Deleting the node should set this value to false, but we set it here for
        // explicitness.
        self.list[node].inList = false;
        delete self.list[node];
    }

    /**
    * @notice Insert a node at the beginning of the list.
    *
    * @param self The list being used.
    * @param node The node to insert at the beginning of the list.
    */
    function prepend(List storage self, address node) internal {
        // isInList(node) is checked in insertBefore

        insertBefore(self, begin(self), node);
    }

    /**
    * @notice Insert a node at the end of the list.
    *
    * @param self The list being used.
    * @param node The node to insert at the end of the list.
    */
    function append(List storage self, address node) internal {
        // isInList(node) is checked in insertBefore

        insertAfter(self, end(self), node);
    }

    function swap(List storage self, address left, address right) internal {
        // isInList(left) and isInList(right) are checked in remove

        address previousRight = self.list[right].previous;
        remove(self, right);
        insertAfter(self, left, right);
        remove(self, left);
        insertAfter(self, previousRight, left);
    }

    function isInList(List storage self, address node) internal view returns (bool) {
        return self.list[node].inList;
    }

    /**
    * @notice Get the node at the beginning of a double linked list.
    *
    * @param self The list being used.
    *
    * @return A address identifying the node at the beginning of the double
    * linked list.
    */
    function begin(List storage self) internal view returns (address) {
        return self.list[NULL].next;
    }

    /**
    * @notice Get the node at the end of a double linked list.
    *
    * @param self The list being used.
    *
    * @return A address identifying the node at the end of the double linked
    * list.
    */
    function end(List storage self) internal view returns (address) {
        return self.list[NULL].previous;
    }

    function next(List storage self, address node) internal view returns (address) {
        require(isInList(self, node), "not in list");
        return self.list[node].next;
    }

    function previous(List storage self, address node) internal view returns (address) {
        require(isInList(self, node), "not in list");
        return self.list[node].previous;
    }

}

/// @notice This contract stores data and funds for the DarknodeRegistry
/// contract. The data / fund logic and storage have been separated to improve
/// upgradability.
contract DarknodeRegistryStore is Ownable {
    string public VERSION; // Passed in as a constructor parameter.

    /// @notice Darknodes are stored in the darknode struct. The owner is the
    /// address that registered the darknode, the bond is the amount of REN that
    /// was transferred during registration, and the public key is the
    /// encryption key that should be used when sending sensitive information to
    /// the darknode.
    struct Darknode {
        // The owner of a Darknode is the address that called the register
        // function. The owner is the only address that is allowed to
        // deregister the Darknode, unless the Darknode is slashed for
        // malicious behavior.
        address owner;

        // The bond is the amount of REN submitted as a bond by the Darknode.
        // This amount is reduced when the Darknode is slashed for malicious
        // behavior.
        uint256 bond;

        // The block number at which the Darknode is considered registered.
        uint256 registeredAt;

        // The block number at which the Darknode is considered deregistered.
        uint256 deregisteredAt;

        // The public key used by this Darknode for encrypting sensitive data
        // off chain. It is assumed that the Darknode has access to the
        // respective private key, and that there is an agreement on the format
        // of the public key.
        bytes publicKey;
    }

    /// Registry data.
    mapping(address => Darknode) private darknodeRegistry;
    LinkedList.List private darknodes;

    // RepublicToken.
    RepublicToken public ren;

    /// @notice The contract constructor.
    ///
    /// @param _VERSION A string defining the contract version.
    /// @param _ren The address of the RepublicToken contract.
    constructor(
        string _VERSION,
        RepublicToken _ren
    ) public {
        VERSION = _VERSION;
        ren = _ren;
    }

    /// @notice Instantiates a darknode and appends it to the darknodes
    /// linked-list.
    ///
    /// @param _darknodeID The darknode's ID.
    /// @param _darknodeOwner The darknode's owner's address
    /// @param _bond The darknode's bond value
    /// @param _publicKey The darknode's public key
    /// @param _registeredAt The time stamp when the darknode is registered.
    /// @param _deregisteredAt The time stamp when the darknode is deregistered.
    function appendDarknode(
        address _darknodeID,
        address _darknodeOwner,
        uint256 _bond,
        bytes _publicKey,
        uint256 _registeredAt,
        uint256 _deregisteredAt
    ) external onlyOwner {
        Darknode memory darknode = Darknode({
            owner: _darknodeOwner,
            bond: _bond,
            publicKey: _publicKey,
            registeredAt: _registeredAt,
            deregisteredAt: _deregisteredAt
        });
        darknodeRegistry[_darknodeID] = darknode;
        LinkedList.append(darknodes, _darknodeID);
    }

    /// @notice Returns the address of the first darknode in the store
    function begin() external view onlyOwner returns(address) {
        return LinkedList.begin(darknodes);
    }

    /// @notice Returns the address of the next darknode in the store after the
    /// given address.
    function next(address darknodeID) external view onlyOwner returns(address) {
        return LinkedList.next(darknodes, darknodeID);
    }

    /// @notice Removes a darknode from the store and transfers its bond to the
    /// owner of this contract.
    function removeDarknode(address darknodeID) external onlyOwner {
        uint256 bond = darknodeRegistry[darknodeID].bond;
        delete darknodeRegistry[darknodeID];
        LinkedList.remove(darknodes, darknodeID);
        require(ren.transfer(owner, bond), "bond transfer failed");
    }

    /// @notice Updates the bond of the darknode. If the bond is being
    /// decreased, the difference is sent to the owner of this contract.
    function updateDarknodeBond(address darknodeID, uint256 bond) external onlyOwner {
        uint256 previousBond = darknodeRegistry[darknodeID].bond;
        darknodeRegistry[darknodeID].bond = bond;
        if (previousBond > bond) {
            require(ren.transfer(owner, previousBond - bond), "cannot transfer bond");
        }
    }

    /// @notice Updates the deregistration timestamp of a darknode.
    function updateDarknodeDeregisteredAt(address darknodeID, uint256 deregisteredAt) external onlyOwner {
        darknodeRegistry[darknodeID].deregisteredAt = deregisteredAt;
    }

    /// @notice Returns the owner of a given darknode.
    function darknodeOwner(address darknodeID) external view onlyOwner returns (address) {
        return darknodeRegistry[darknodeID].owner;
    }

    /// @notice Returns the bond of a given darknode.
    function darknodeBond(address darknodeID) external view onlyOwner returns (uint256) {
        return darknodeRegistry[darknodeID].bond;
    }

    /// @notice Returns the registration time of a given darknode.
    function darknodeRegisteredAt(address darknodeID) external view onlyOwner returns (uint256) {
        return darknodeRegistry[darknodeID].registeredAt;
    }

    /// @notice Returns the deregistration time of a given darknode.
    function darknodeDeregisteredAt(address darknodeID) external view onlyOwner returns (uint256) {
        return darknodeRegistry[darknodeID].deregisteredAt;
    }

    /// @notice Returns the encryption public key of a given darknode.
    function darknodePublicKey(address darknodeID) external view onlyOwner returns (bytes) {
        return darknodeRegistry[darknodeID].publicKey;
    }
}

/// @notice DarknodeRegistry is responsible for the registration and
/// deregistration of Darknodes.
contract DarknodeRegistry is Ownable {
    string public VERSION; // Passed in as a constructor parameter.

    /// @notice Darknode pods are shuffled after a fixed number of blocks.
    /// An Epoch stores an epoch hash used as an (insecure) RNG seed, and the
    /// blocknumber which restricts when the next epoch can be called.
    struct Epoch {
        uint256 epochhash;
        uint256 blocknumber;
    }

    uint256 public numDarknodes;
    uint256 public numDarknodesNextEpoch;
    uint256 public numDarknodesPreviousEpoch;

    /// Variables used to parameterize behavior.
    uint256 public minimumBond;
    uint256 public minimumPodSize;
    uint256 public minimumEpochInterval;
    address public slasher;

    /// When one of the above variables is modified, it is only updated when the
    /// next epoch is called. These variables store the values for the next epoch.
    uint256 public nextMinimumBond;
    uint256 public nextMinimumPodSize;
    uint256 public nextMinimumEpochInterval;
    address public nextSlasher;

    /// The current and previous epoch
    Epoch public currentEpoch;
    Epoch public previousEpoch;

    /// Republic ERC20 token contract used to transfer bonds.
    RepublicToken public ren;

    /// Darknode Registry Store is the storage contract for darknodes.
    DarknodeRegistryStore public store;

    /// @notice Emitted when a darknode is registered.
    /// @param _darknodeID The darknode ID that was registered.
    /// @param _bond The amount of REN that was transferred as bond.
    event LogDarknodeRegistered(address _darknodeID, uint256 _bond);

    /// @notice Emitted when a darknode is deregistered.
    /// @param _darknodeID The darknode ID that was deregistered.
    event LogDarknodeDeregistered(address _darknodeID);

    /// @notice Emitted when a refund has been made.
    /// @param _owner The address that was refunded.
    /// @param _amount The amount of REN that was refunded.
    event LogDarknodeOwnerRefunded(address _owner, uint256 _amount);

    /// @notice Emitted when a new epoch has begun.
    event LogNewEpoch();

    /// @notice Emitted when a constructor parameter has been updated.
    event LogMinimumBondUpdated(uint256 previousMinimumBond, uint256 nextMinimumBond);
    event LogMinimumPodSizeUpdated(uint256 previousMinimumPodSize, uint256 nextMinimumPodSize);
    event LogMinimumEpochIntervalUpdated(uint256 previousMinimumEpochInterval, uint256 nextMinimumEpochInterval);
    event LogSlasherUpdated(address previousSlasher, address nextSlasher);

    /// @notice Only allow the owner that registered the darknode to pass.
    modifier onlyDarknodeOwner(address _darknodeID) {
        require(store.darknodeOwner(_darknodeID) == msg.sender, "must be darknode owner");
        _;
    }

    /// @notice Only allow unregistered darknodes.
    modifier onlyRefunded(address _darknodeID) {
        require(isRefunded(_darknodeID), "must be refunded or never registered");
        _;
    }

    /// @notice Only allow refundable darknodes.
    modifier onlyRefundable(address _darknodeID) {
        require(isRefundable(_darknodeID), "must be deregistered for at least one epoch");
        _;
    }

    /// @notice Only allowed registered nodes without a pending deregistration to
    /// deregister
    modifier onlyDeregisterable(address _darknodeID) {
        require(isDeregisterable(_darknodeID), "must be deregisterable");
        _;
    }

    /// @notice Only allow the Slasher contract.
    modifier onlySlasher() {
        require(slasher == msg.sender, "must be slasher");
        _;
    }

    /// @notice The contract constructor.
    ///
    /// @param _VERSION A string defining the contract version.
    /// @param _renAddress The address of the RepublicToken contract.
    /// @param _storeAddress The address of the DarknodeRegistryStore contract.
    /// @param _minimumBond The minimum bond amount that can be submitted by a
    ///        Darknode.
    /// @param _minimumPodSize The minimum size of a Darknode pod.
    /// @param _minimumEpochInterval The minimum number of blocks between
    ///        epochs.
    constructor(
        string _VERSION,
        RepublicToken _renAddress,
        DarknodeRegistryStore _storeAddress,
        uint256 _minimumBond,
        uint256 _minimumPodSize,
        uint256 _minimumEpochInterval
    ) public {
        VERSION = _VERSION;

        store = _storeAddress;
        ren = _renAddress;

        minimumBond = _minimumBond;
        nextMinimumBond = minimumBond;

        minimumPodSize = _minimumPodSize;
        nextMinimumPodSize = minimumPodSize;

        minimumEpochInterval = _minimumEpochInterval;
        nextMinimumEpochInterval = minimumEpochInterval;

        currentEpoch = Epoch({
            epochhash: uint256(blockhash(block.number - 1)),
            blocknumber: block.number
        });
        numDarknodes = 0;
        numDarknodesNextEpoch = 0;
        numDarknodesPreviousEpoch = 0;
    }

    /// @notice Register a darknode and transfer the bond to this contract. The
    /// caller must provide a public encryption key for the darknode as well as
    /// a bond in REN. The bond must be provided as an ERC20 allowance. The dark
    /// node will remain pending registration until the next epoch. Only after
    /// this period can the darknode be deregistered. The caller of this method
    /// will be stored as the owner of the darknode.
    ///
    /// @param _darknodeID The darknode ID that will be registered.
    /// @param _publicKey The public key of the darknode. It is stored to allow
    ///        other darknodes and traders to encrypt messages to the trader.
    /// @param _bond The bond that will be paid. It must be greater than, or
    ///        equal to, the minimum bond.
    function register(address _darknodeID, bytes _publicKey, uint256 _bond) external onlyRefunded(_darknodeID) {
        // REN allowance
        require(_bond >= minimumBond, "insufficient bond");
        // require(ren.allowance(msg.sender, address(this)) >= _bond);
        require(ren.transferFrom(msg.sender, address(this), _bond), "bond transfer failed");
        ren.transfer(address(store), _bond);

        // Flag this darknode for registration
        store.appendDarknode(
            _darknodeID,
            msg.sender,
            _bond,
            _publicKey,
            currentEpoch.blocknumber + minimumEpochInterval,
            0
        );

        numDarknodesNextEpoch += 1;

        // Emit an event.
        emit LogDarknodeRegistered(_darknodeID, _bond);
    }

    /// @notice Deregister a darknode. The darknode will not be deregistered
    /// until the end of the epoch. After another epoch, the bond can be
    /// refunded by calling the refund method.
    /// @param _darknodeID The darknode ID that will be deregistered. The caller
    ///        of this method store.darknodeRegisteredAt(_darknodeID) must be
    //         the owner of this darknode.
    function deregister(address _darknodeID) external onlyDeregisterable(_darknodeID) onlyDarknodeOwner(_darknodeID) {
        // Flag the darknode for deregistration
        store.updateDarknodeDeregisteredAt(_darknodeID, currentEpoch.blocknumber + minimumEpochInterval);
        numDarknodesNextEpoch -= 1;

        // Emit an event
        emit LogDarknodeDeregistered(_darknodeID);
    }

    /// @notice Progress the epoch if it is possible to do so. This captures
    /// the current timestamp and current blockhash and overrides the current
    /// epoch.
    function epoch() external {
        if (previousEpoch.blocknumber == 0) {
            // The first epoch must be called by the owner of the contract
            require(msg.sender == owner, "not authorized (first epochs)");
        }

        // Require that the epoch interval has passed
        require(block.number >= currentEpoch.blocknumber + minimumEpochInterval, "epoch interval has not passed");
        uint256 epochhash = uint256(blockhash(block.number - 1));

        // Update the epoch hash and timestamp
        previousEpoch = currentEpoch;
        currentEpoch = Epoch({
            epochhash: epochhash,
            blocknumber: block.number
        });

        // Update the registry information
        numDarknodesPreviousEpoch = numDarknodes;
        numDarknodes = numDarknodesNextEpoch;

        // If any update functions have been called, update the values now
        if (nextMinimumBond != minimumBond) {
            minimumBond = nextMinimumBond;
            emit LogMinimumBondUpdated(minimumBond, nextMinimumBond);
        }
        if (nextMinimumPodSize != minimumPodSize) {
            minimumPodSize = nextMinimumPodSize;
            emit LogMinimumPodSizeUpdated(minimumPodSize, nextMinimumPodSize);
        }
        if (nextMinimumEpochInterval != minimumEpochInterval) {
            minimumEpochInterval = nextMinimumEpochInterval;
            emit LogMinimumEpochIntervalUpdated(minimumEpochInterval, nextMinimumEpochInterval);
        }
        if (nextSlasher != slasher) {
            slasher = nextSlasher;
            emit LogSlasherUpdated(slasher, nextSlasher);
        }

        // Emit an event
        emit LogNewEpoch();
    }

    /// @notice Allows the contract owner to transfer ownership of the
    /// DarknodeRegistryStore.
    /// @param _newOwner The address to transfer the ownership to.
    function transferStoreOwnership(address _newOwner) external onlyOwner {
        store.transferOwnership(_newOwner);
    }

    /// @notice Allows the contract owner to update the minimum bond.
    /// @param _nextMinimumBond The minimum bond amount that can be submitted by
    ///        a darknode.
    function updateMinimumBond(uint256 _nextMinimumBond) external onlyOwner {
        // Will be updated next epoch
        nextMinimumBond = _nextMinimumBond;
    }

    /// @notice Allows the contract owner to update the minimum pod size.
    /// @param _nextMinimumPodSize The minimum size of a pod.
    function updateMinimumPodSize(uint256 _nextMinimumPodSize) external onlyOwner {
        // Will be updated next epoch
        nextMinimumPodSize = _nextMinimumPodSize;
    }

    /// @notice Allows the contract owner to update the minimum epoch interval.
    /// @param _nextMinimumEpochInterval The minimum number of blocks between epochs.
    function updateMinimumEpochInterval(uint256 _nextMinimumEpochInterval) external onlyOwner {
        // Will be updated next epoch
        nextMinimumEpochInterval = _nextMinimumEpochInterval;
    }

    /// @notice Allow the contract owner to update the DarknodeSlasher contract
    /// address.
    /// @param _slasher The new slasher address.
    function updateSlasher(address _slasher) external onlyOwner {
        nextSlasher = _slasher;
    }

    /// @notice Allow the DarknodeSlasher contract to slash half of a darknode's
    /// bond and deregister it. The bond is distributed as follows:
    ///   1/2 is kept by the guilty prover
    ///   1/8 is rewarded to the first challenger
    ///   1/8 is rewarded to the second challenger
    ///   1/4 becomes unassigned
    /// @param _prover The guilty prover whose bond is being slashed
    /// @param _challenger1 The first of the two darknodes who submitted the challenge
    /// @param _challenger2 The second of the two darknodes who submitted the challenge
    function slash(address _prover, address _challenger1, address _challenger2)
        external
        onlySlasher
    {
        uint256 penalty = store.darknodeBond(_prover) / 2;
        uint256 reward = penalty / 4;

        // Slash the bond of the failed prover in half
        store.updateDarknodeBond(_prover, penalty);

        // If the darknode has not been deregistered then deregister it
        if (isDeregisterable(_prover)) {
            store.updateDarknodeDeregisteredAt(_prover, currentEpoch.blocknumber + minimumEpochInterval);
            numDarknodesNextEpoch -= 1;
            emit LogDarknodeDeregistered(_prover);
        }

        // Reward the challengers with less than the penalty so that it is not
        // worth challenging yourself
        ren.transfer(store.darknodeOwner(_challenger1), reward);
        ren.transfer(store.darknodeOwner(_challenger2), reward);
    }

    /// @notice Refund the bond of a deregistered darknode. This will make the
    /// darknode available for registration again. Anyone can call this function
    /// but the bond will always be refunded to the darknode owner.
    ///
    /// @param _darknodeID The darknode ID that will be refunded. The caller
    ///        of this method must be the owner of this darknode.
    function refund(address _darknodeID) external onlyRefundable(_darknodeID) {
        address darknodeOwner = store.darknodeOwner(_darknodeID);

        // Remember the bond amount
        uint256 amount = store.darknodeBond(_darknodeID);

        // Erase the darknode from the registry
        store.removeDarknode(_darknodeID);

        // Refund the owner by transferring REN
        ren.transfer(darknodeOwner, amount);

        // Emit an event.
        emit LogDarknodeOwnerRefunded(darknodeOwner, amount);
    }

    /// @notice Retrieves the address of the account that registered a darknode.
    /// @param _darknodeID The ID of the darknode to retrieve the owner for.
    function getDarknodeOwner(address _darknodeID) external view returns (address) {
        return store.darknodeOwner(_darknodeID);
    }

    /// @notice Retrieves the bond amount of a darknode in 10^-18 REN.
    /// @param _darknodeID The ID of the darknode to retrieve the bond for.
    function getDarknodeBond(address _darknodeID) external view returns (uint256) {
        return store.darknodeBond(_darknodeID);
    }

    /// @notice Retrieves the encryption public key of the darknode.
    /// @param _darknodeID The ID of the darknode to retrieve the public key for.
    function getDarknodePublicKey(address _darknodeID) external view returns (bytes) {
        return store.darknodePublicKey(_darknodeID);
    }

    /// @notice Retrieves a list of darknodes which are registered for the
    /// current epoch.
    /// @param _start A darknode ID used as an offset for the list. If _start is
    ///        0x0, the first dark node will be used. _start won't be
    ///        included it is not registered for the epoch.
    /// @param _count The number of darknodes to retrieve starting from _start.
    ///        If _count is 0, all of the darknodes from _start are
    ///        retrieved. If _count is more than the remaining number of
    ///        registered darknodes, the rest of the list will contain
    ///        0x0s.
    function getDarknodes(address _start, uint256 _count) external view returns (address[]) {
        uint256 count = _count;
        if (count == 0) {
            count = numDarknodes;
        }
        return getDarknodesFromEpochs(_start, count, false);
    }

    /// @notice Retrieves a list of darknodes which were registered for the
    /// previous epoch. See `getDarknodes` for the parameter documentation.
    function getPreviousDarknodes(address _start, uint256 _count) external view returns (address[]) {
        uint256 count = _count;
        if (count == 0) {
            count = numDarknodesPreviousEpoch;
        }
        return getDarknodesFromEpochs(_start, count, true);
    }

    /// @notice Returns whether a darknode is scheduled to become registered
    /// at next epoch.
    /// @param _darknodeID The ID of the darknode to return
    function isPendingRegistration(address _darknodeID) external view returns (bool) {
        uint256 registeredAt = store.darknodeRegisteredAt(_darknodeID);
        return registeredAt != 0 && registeredAt > currentEpoch.blocknumber;
    }

    /// @notice Returns if a darknode is in the pending deregistered state. In
    /// this state a darknode is still considered registered.
    function isPendingDeregistration(address _darknodeID) external view returns (bool) {
        uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID);
        return deregisteredAt != 0 && deregisteredAt > currentEpoch.blocknumber;
    }

    /// @notice Returns if a darknode is in the deregistered state.
    function isDeregistered(address _darknodeID) public view returns (bool) {
        uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID);
        return deregisteredAt != 0 && deregisteredAt <= currentEpoch.blocknumber;
    }

    /// @notice Returns if a darknode can be deregistered. This is true if the
    /// darknodes is in the registered state and has not attempted to
    /// deregister yet.
    function isDeregisterable(address _darknodeID) public view returns (bool) {
        uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID);
        // The Darknode is currently in the registered state and has not been
        // transitioned to the pending deregistration, or deregistered, state
        return isRegistered(_darknodeID) && deregisteredAt == 0;
    }

    /// @notice Returns if a darknode is in the refunded state. This is true
    /// for darknodes that have never been registered, or darknodes that have
    /// been deregistered and refunded.
    function isRefunded(address _darknodeID) public view returns (bool) {
        uint256 registeredAt = store.darknodeRegisteredAt(_darknodeID);
        uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID);
        return registeredAt == 0 && deregisteredAt == 0;
    }

    /// @notice Returns if a darknode is refundable. This is true for darknodes
    /// that have been in the deregistered state for one full epoch.
    function isRefundable(address _darknodeID) public view returns (bool) {
        return isDeregistered(_darknodeID) && store.darknodeDeregisteredAt(_darknodeID) <= previousEpoch.blocknumber;
    }

    /// @notice Returns if a darknode is in the registered state.
    function isRegistered(address _darknodeID) public view returns (bool) {
        return isRegisteredInEpoch(_darknodeID, currentEpoch);
    }

    /// @notice Returns if a darknode was in the registered state last epoch.
    function isRegisteredInPreviousEpoch(address _darknodeID) public view returns (bool) {
        return isRegisteredInEpoch(_darknodeID, previousEpoch);
    }

    /// @notice Returns if a darknode was in the registered state for a given
    /// epoch.
    /// @param _darknodeID The ID of the darknode
    /// @param _epoch One of currentEpoch, previousEpoch
    function isRegisteredInEpoch(address _darknodeID, Epoch _epoch) private view returns (bool) {
        uint256 registeredAt = store.darknodeRegisteredAt(_darknodeID);
        uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID);
        bool registered = registeredAt != 0 && registeredAt <= _epoch.blocknumber;
        bool notDeregistered = deregisteredAt == 0 || deregisteredAt > _epoch.blocknumber;
        // The Darknode has been registered and has not yet been deregistered,
        // although it might be pending deregistration
        return registered && notDeregistered;
    }

    /// @notice Returns a list of darknodes registered for either the current
    /// or the previous epoch. See `getDarknodes` for documentation on the
    /// parameters `_start` and `_count`.
    /// @param _usePreviousEpoch If true, use the previous epoch, otherwise use
    ///        the current epoch.
    function getDarknodesFromEpochs(address _start, uint256 _count, bool _usePreviousEpoch) private view returns (address[]) {
        uint256 count = _count;
        if (count == 0) {
            count = numDarknodes;
        }

        address[] memory nodes = new address[](count);

        // Begin with the first node in the list
        uint256 n = 0;
        address next = _start;
        if (next == 0x0) {
            next = store.begin();
        }

        // Iterate until all registered Darknodes have been collected
        while (n < count) {
            if (next == 0x0) {
                break;
            }
            // Only include Darknodes that are currently registered
            bool includeNext;
            if (_usePreviousEpoch) {
                includeNext = isRegisteredInPreviousEpoch(next);
            } else {
                includeNext = isRegistered(next);
            }
            if (!includeNext) {
                next = store.next(next);
                continue;
            }
            nodes[n] = next;
            next = store.next(next);
            n += 1;
        }
        return nodes;
    }
}

/**
 * @title Math
 * @dev Assorted math operations
 */
library Math {
  function max64(uint64 a, uint64 b) internal pure returns (uint64) {
    return a >= b ? a : b;
  }

  function min64(uint64 a, uint64 b) internal pure returns (uint64) {
    return a < b ? a : b;
  }

  function max256(uint256 a, uint256 b) internal pure returns (uint256) {
    return a >= b ? a : b;
  }

  function min256(uint256 a, uint256 b) internal pure returns (uint256) {
    return a < b ? a : b;
  }
}

/// @notice Implements safeTransfer, safeTransferFrom and
/// safeApprove for CompatibleERC20.
///
/// See https://github.com/ethereum/solidity/issues/4116
///
/// This library allows interacting with ERC20 tokens that implement any of
/// these interfaces:
///
/// (1) transfer returns true on success, false on failure
/// (2) transfer returns true on success, reverts on failure
/// (3) transfer returns nothing on success, reverts on failure
///
/// Additionally, safeTransferFromWithFees will return the final token
/// value received after accounting for token fees.
library CompatibleERC20Functions {
    using SafeMath for uint256;

    /// @notice Calls transfer on the token and reverts if the call fails.
    function safeTransfer(address token, address to, uint256 amount) internal {
        CompatibleERC20(token).transfer(to, amount);
        require(previousReturnValue(), "transfer failed");
    }

    /// @notice Calls transferFrom on the token and reverts if the call fails.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        CompatibleERC20(token).transferFrom(from, to, amount);
        require(previousReturnValue(), "transferFrom failed");
    }

    /// @notice Calls approve on the token and reverts if the call fails.
    function safeApprove(address token, address spender, uint256 amount) internal {
        CompatibleERC20(token).approve(spender, amount);
        require(previousReturnValue(), "approve failed");
    }

    /// @notice Calls transferFrom on the token, reverts if the call fails and
    /// returns the value transferred after fees.
    function safeTransferFromWithFees(address token, address from, address to, uint256 amount) internal returns (uint256) {
        uint256 balancesBefore = CompatibleERC20(token).balanceOf(to);
        CompatibleERC20(token).transferFrom(from, to, amount);
        require(previousReturnValue(), "transferFrom failed");
        uint256 balancesAfter = CompatibleERC20(token).balanceOf(to);
        return Math.min256(amount, balancesAfter.sub(balancesBefore));
    }

    /// @notice Checks the return value of the previous function. Returns true
    /// if the previous function returned 32 non-zero bytes or returned zero
    /// bytes.
    function previousReturnValue() private pure returns (bool)
    {
        uint256 returnData = 0;

        assembly { /* solium-disable-line security/no-inline-assembly */
            // Switch on the number of bytes returned by the previous call
            switch returndatasize

            // 0 bytes: ERC20 of type (3), did not throw
            case 0 {
                returnData := 1
            }

            // 32 bytes: ERC20 of types (1) or (2)
            case 32 {
                // Copy the return data into scratch space
                returndatacopy(0x0, 0x0, 32)

                // Load  the return data into returnData
                returnData := mload(0x0)
            }

            // Other return size: return false
            default { }
        }

        return returnData != 0;
    }
}

/// @notice ERC20 interface which doesn't specify the return type for transfer,
/// transferFrom and approve.
interface CompatibleERC20 {
    // Modified to not return boolean
    function transfer(address to, uint256 value) external;
    function transferFrom(address from, address to, uint256 value) external;
    function approve(address spender, uint256 value) external;

    // Not modifier
    function totalSupply() external view returns (uint256);
    function balanceOf(address who) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/// @notice The DarknodeRewardVault contract is responsible for holding fees
/// for darknodes for settling orders. Fees can be withdrawn to the address of
/// the darknode's operator. Fees can be in ETH or in ERC20 tokens.
/// Docs: https://github.com/republicprotocol/republic-sol/blob/master/docs/02-darknode-reward-vault.md
contract DarknodeRewardVault is Ownable {
    using SafeMath for uint256;
    using CompatibleERC20Functions for CompatibleERC20;

    string public VERSION; // Passed in as a constructor parameter.

    /// @notice The special address for Ether.
    address constant public ETHEREUM = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    DarknodeRegistry public darknodeRegistry;

    mapping(address => mapping(address => uint256)) public darknodeBalances;

    event LogDarknodeRegistryUpdated(DarknodeRegistry previousDarknodeRegistry, DarknodeRegistry nextDarknodeRegistry);

    /// @notice The contract constructor.
    ///
    /// @param _VERSION A string defining the contract version.
    /// @param _darknodeRegistry The DarknodeRegistry contract that is used by
    ///        the vault to lookup Darknode owners.
    constructor(string _VERSION, DarknodeRegistry _darknodeRegistry) public {
        VERSION = _VERSION;
        darknodeRegistry = _darknodeRegistry;
    }

    function updateDarknodeRegistry(DarknodeRegistry _newDarknodeRegistry) public onlyOwner {
        emit LogDarknodeRegistryUpdated(darknodeRegistry, _newDarknodeRegistry);
        darknodeRegistry = _newDarknodeRegistry;
    }

    /// @notice Deposit fees into the vault for a Darknode. The Darknode
    /// registration is not checked (to reduce gas fees); the caller must be
    /// careful not to call this function for a Darknode that is not registered
    /// otherwise any fees deposited to that Darknode can be withdrawn by a
    /// malicious adversary (by registering the Darknode before the honest
    /// party and claiming ownership).
    ///
    /// @param _darknode The address of the Darknode that will receive the
    ///        fees.
    /// @param _token The address of the ERC20 token being used to pay the fee.
    ///        A special address is used for Ether.
    /// @param _value The amount of fees in the smallest unit of the token.
    function deposit(address _darknode, ERC20 _token, uint256 _value) public payable {
        uint256 receivedValue = _value;
        if (address(_token) == ETHEREUM) {
            require(msg.value == _value, "mismatched ether value");
        } else {
            require(msg.value == 0, "unexpected ether value");
            receivedValue = CompatibleERC20(_token).safeTransferFromWithFees(msg.sender, address(this), _value);
        }
        darknodeBalances[_darknode][_token] = darknodeBalances[_darknode][_token].add(receivedValue);
    }

    /// @notice Withdraw fees earned by a Darknode. The fees will be sent to
    /// the owner of the Darknode. If a Darknode is not registered the fees
    /// cannot be withdrawn.
    ///
    /// @param _darknode The address of the Darknode whose fees are being
    ///        withdrawn. The owner of this Darknode will receive the fees.
    /// @param _token The address of the ERC20 token to withdraw.
    function withdraw(address _darknode, ERC20 _token) public {
        address darknodeOwner = darknodeRegistry.getDarknodeOwner(address(_darknode));

        require(darknodeOwner != 0x0, "invalid darknode owner");

        uint256 value = darknodeBalances[_darknode][_token];
        darknodeBalances[_darknode][_token] = 0;

        if (address(_token) == ETHEREUM) {
            darknodeOwner.transfer(value);
        } else {
            CompatibleERC20(_token).safeTransfer(darknodeOwner, value);
        }
    }

}

Contract ABI
[{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"darknodeBalances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_darknode","type":"address"},{"name":"_token","type":"address"},{"name":"_value","type":"uint256"}],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"darknodeRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newDarknodeRegistry","type":"address"}],"name":"updateDarknodeRegistry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ETHEREUM","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_darknode","type":"address"},{"name":"_token","type":"address"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"VERSION","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_VERSION","type":"string"},{"name":"_darknodeRegistry","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousDarknodeRegistry","type":"address"},{"indexed":false,"name":"nextDarknodeRegistry","type":"address"}],"name":"LogDarknodeRegistryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

Contract Creation Code
60806040523480156200001157600080fd5b50604051620015af380380620015af8339810180604052810190808051820192919060200180519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600190805190602001906200009b929190620000e5565b5080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505062000194565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200012857805160ff191683800117855562000159565b8280016001018555821562000159579182015b82811115620001585782518255916020019190600101906200013b565b5b5090506200016891906200016c565b5090565b6200019191905b808211156200018d57600081600090555060010162000173565b5090565b90565b61140b80620001a46000396000f3006080604052600436106100a4576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806370324b77146100a9578063715018a6146101205780638340f549146101375780638da5cb5b146101975780639e45e0d0146101ee578063aaff096d14610245578063f2fde38b14610288578063f7cdf47c146102cb578063f940e38514610322578063ffa1ad7414610385575b600080fd5b3480156100b557600080fd5b5061010a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610415565b6040518082815260200191505060405180910390f35b34801561012c57600080fd5b5061013561043a565b005b610195600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061053c565b005b3480156101a357600080fd5b506101ac6107c2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101fa57600080fd5b506102036107e7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561025157600080fd5b50610286600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061080d565b005b34801561029457600080fd5b506102c9600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610965565b005b3480156102d757600080fd5b506102e06109cc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561032e57600080fd5b50610383600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506109e4565b005b34801561039157600080fd5b5061039a610d37565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103da5780820151818401526020810190506103bf565b50505050905090810190601f1680156104075780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6003602052816000526040600020602052806000526040600020600091509150505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561049557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482060405160405180910390a260008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600081905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610605578134141515610600576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6d69736d6174636865642065746865722076616c75650000000000000000000081525060200191505060405180910390fd5b6106ad565b60003414151561067d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f756e65787065637465642065746865722076616c75650000000000000000000081525060200191505060405180910390fd5b6106aa3330848673ffffffffffffffffffffffffffffffffffffffff16610dd5909392919063ffffffff16565b90505b61073c81600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461111d90919063ffffffff16565b600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561086857600080fd5b7ff9f6dd5c784f63cc27c1079c73574a73485a6c2e7f7e2181c5eb2be8c693cfb7600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a180600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156109c057600080fd5b6109c981611139565b50565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631cedf8a3856040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015610aa457600080fd5b505af1158015610ab8573d6000803e3d6000fd5b505050506040513d6020811015610ace57600080fd5b8101908080519060200190929190505050915060008273ffffffffffffffffffffffffffffffffffffffff1614151515610b70576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f696e76616c6964206461726b6e6f6465206f776e65720000000000000000000081525060200191505060405180910390fd5b600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610d05578173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610cff573d6000803e3d6000fd5b50610d31565b610d3082828573ffffffffffffffffffffffffffffffffffffffff166112339092919063ffffffff16565b5b50505050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610dcd5780601f10610da257610100808354040283529160200191610dcd565b820191906000526020600020905b815481529060010190602001808311610db057829003601f168201915b505050505081565b60008060008673ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506040513d6020811015610e9f57600080fd5b810190808051906020019092919050505091508673ffffffffffffffffffffffffffffffffffffffff166323b872dd8787876040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b158015610f8957600080fd5b505af1158015610f9d573d6000803e3d6000fd5b50505050610fa961136f565b151561101d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f7472616e7366657246726f6d206661696c65640000000000000000000000000081525060200191505060405180910390fd5b8673ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b1580156110b857600080fd5b505af11580156110cc573d6000803e3d6000fd5b505050506040513d60208110156110e257600080fd5b810190808051906020019092919050505090506111118461110c84846113ad90919063ffffffff16565b6113c6565b92505050949350505050565b6000818301905082811015151561113057fe5b80905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561117557600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b1580156112d657600080fd5b505af11580156112ea573d6000803e3d6000fd5b505050506112f661136f565b151561136a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f7472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b505050565b600080600090503d6000811461138c5760208114611395576113a1565b600191506113a1565b60206000803e60005191505b50600081141591505090565b60008282111515156113bb57fe5b818303905092915050565b60008183106113d557816113d7565b825b9050929150505600a165627a7a7230582039fb41d820a376d002935ea4d6a98845cf625c91279852ff84273ff39b54d0d10029000000000000000000000000000000000000000000000000000000000000004000000000000000000000000034bd421c7948bc16f826fd99f9b785929b1216330000000000000000000000000000000000000000000000000000000000000005312e302e32000000000000000000000000000000000000000000000000000000


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

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 00000000000000000000000034bd421c7948bc16f826fd99f9b785929b121633
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [3] : 312e302e32000000000000000000000000000000000000000000000000000000


   Swarm Source:
bzzr://39fb41d820a376d002935ea4d6a98845cf625c91279852ff84273ff39b54d0d1
Block Age transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.