Contract 0x3baa64a4401bbe18865547e916a9be8e6dd89a5a

 

TxHash Block Age From To Value [TxFee]
0xaa8c1a2fc1b00126bbfd5ef7151ef8868811146d18393efa157ee5c7c88af852723267710 hrs 53 mins ago0x2c82e14352e98c931852d9bb5f0760e36942cc3c  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.001226675
0x2d0957869d2909b85fd583d03779b2030abbbe8f73382ad1db8a2f0cb1864e8d723092620 hrs 46 mins ago0x34a4b73100d11815ee4bb0ebcc86ba5824b12134  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000006507945 Ether0.001549986
0x713344547855825e7444f744bc7d2f85613fdd7700429b68039477f6ded7cd8172250672 days 6 hrs ago0xf563f100df419ccde59bfbe0692fc4c5bfe01706  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000006507945 Ether0.000516662
0xff73f2ea44d939f1edc6f2be88823632c69774ae883b6c1fc37fd5eff2e927d372158854 days 11 hrs ago0x1b6229fc57d56cc4f4efc2b1d6abd0e5e221783b  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0013939881
0x74e17b0ce8825bac4e36eb2a3c50142eeac48e33d5b6e333b964b8b3a1b20b7072131615 days 3 hrs ago0xb93386b6ca38c8f28e872f2a9b9b5176967946d1  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003005937
0xd2dd7246a38d4931e9a23390fe4c580d71f0ec9ccf31d76497c9bbb37258a06372121715 days 8 hrs ago0x8ee9be167874be39fe3b41e09a5166ff283fe21a  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000006507945 Ether0.0005737263
0xbb27d538bbe663975ef2227bbdc6172ba0fe0bfd4aada65e8d91d9bd5f68f66072121715 days 8 hrs ago0x8ee9be167874be39fe3b41e09a5166ff283fe21a  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000006507945 Ether0.0005424951
0x8189e77ae83e48f56eebf7ffafa516893e4e3f5bbcfc041ea048118b8f4a016c72117545 days 11 hrs ago0x8ee9be167874be39fe3b41e09a5166ff283fe21a  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000006507945 Ether0.000516534
0x4e971039094117d8671a97d57676099814cdb41185f042024ee6c7bb2ffa6be272103455 days 18 hrs ago0xbc8dafeaca658ae0857c80d8aa6de4d487577c63  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.005424951
0xa6bc794a19b12bebede82dc1613454642dc09245c691090bfb84e05c24a20ebd72098245 days 21 hrs ago0xf563f100df419ccde59bfbe0692fc4c5bfe01706  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003099972
0x9797670ee6f62032a7b27f4dfedd6f6b9e6a1a2ca8e0d788ce6ae6a228d99bd572095555 days 23 hrs ago0xd714dd60e22bbb1cbafd0e40de5cfa7bbdd3f3c8  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.00001301589 Ether0.0002919972
0x5cffe84e8b079dcccc2062acbe5cda106c73b58c5b627757b41bccb4c33d64f672092436 days 58 mins ago0xfdaaefcca674fdc8b326454f9bd23fab43b92e60  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.00058571505 Ether0.0001858901
0x7fcb5b8c72d5504accf6a4c36c12a1de63187f5ea49fa24107f5b6378af5318372083366 days 6 hrs ago0x51df0af74a0dbae16cb845b46daf2a35cb1d4168  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003279972
0xf8dccb09eacc1279e7ea0efcd27192e1afca977246012501f4f07ae3a9a0e1d272082646 days 6 hrs ago0x1d32f2acb832afc3d8c8ffb3be20e8dc7faac507  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000006507945 Ether0.0003874005
0x4e8caec2d111b18eb5349a0be907dc129833b2036ec85e44a045b8d849f3efa272080906 days 7 hrs ago0x8ee9be167874be39fe3b41e09a5166ff283fe21a  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003874965
0x8416a19f104518d2e7d0e541548da7937902ddc83398c811a1bcf7172f92dbda72079936 days 8 hrs ago0x51df0af74a0dbae16cb845b46daf2a35cb1d4168  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003099972
0x106d36aacb502af6ab2e981522295782faba385762f6707d8e553bcfc557c33972079836 days 8 hrs ago0x51df0af74a0dbae16cb845b46daf2a35cb1d4168  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003099204
0x373eacbadfd220cbb0788e15c215880c143b3d4954d1419aaf634768989b2cad72079796 days 8 hrs ago0x1b6229fc57d56cc4f4efc2b1d6abd0e5e221783b  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003099204
0xd566010e084cc6bffb5857c1642d56f715607b1ee3cf80ac64cbeaa443bd7db372079796 days 8 hrs ago0x1b6229fc57d56cc4f4efc2b1d6abd0e5e221783b  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003099204
0xc21b0fbaf05e0d77be29407ffba0d10931e73838c616cd6a526f8b64d743475d72079766 days 8 hrs ago0x1b6229fc57d56cc4f4efc2b1d6abd0e5e221783b  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0002841641
0x1d2797b02c593bd486f7ca4c91d5077772db24e8ed874cfad4029a6c52f0861a72078946 days 8 hrs ago0x8ee9be167874be39fe3b41e09a5166ff283fe21a  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.0003099972
0xd686872aadcfc9088b3a3f30b362637f2fd20a89024201215afee5e0067aa2ed72064226 days 17 hrs ago0x7baefd3ef84970077ffb5d8d7aa70ea55dba97a8  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.000774993
0x93df447decd645e1c7ce7d15e0526331b92c9301510aa723241374d15c099cf972064056 days 17 hrs ago0x010afb8548a5d1a3a3d62f58ca0a5a1329974206  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.000774801
0x05e8a149c9ad1ac63157eb01ea9f32bbd29a28fc55f23362cfd8ea824ff9ffb172063836 days 17 hrs ago0x010afb8548a5d1a3a3d62f58ca0a5a1329974206  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000001301589 Ether0.001033324
0xd600ba92966708c4b82f1c533a2ed03f5c2ed0dd620808b680bce3d236959d8272059506 days 19 hrs ago0x8ee9be167874be39fe3b41e09a5166ff283fe21a  IN   0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0.000006507945 Ether0.00258331
[ 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
0xaa8c1a2fc1b00126bbfd5ef7151ef8868811146d18393efa157ee5c7c88af852723267710 hrs 53 mins ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x2d0957869d2909b85fd583d03779b2030abbbe8f73382ad1db8a2f0cb1864e8d723092620 hrs 46 mins ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000006507945 Ether
0x713344547855825e7444f744bc7d2f85613fdd7700429b68039477f6ded7cd8172250672 days 6 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000006507945 Ether
0xff73f2ea44d939f1edc6f2be88823632c69774ae883b6c1fc37fd5eff2e927d372158854 days 11 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x74e17b0ce8825bac4e36eb2a3c50142eeac48e33d5b6e333b964b8b3a1b20b7072131615 days 3 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0xd2dd7246a38d4931e9a23390fe4c580d71f0ec9ccf31d76497c9bbb37258a06372121715 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000006507945 Ether
0xbb27d538bbe663975ef2227bbdc6172ba0fe0bfd4aada65e8d91d9bd5f68f66072121715 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000006507945 Ether
0x8189e77ae83e48f56eebf7ffafa516893e4e3f5bbcfc041ea048118b8f4a016c72117545 days 11 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000006507945 Ether
0x4e971039094117d8671a97d57676099814cdb41185f042024ee6c7bb2ffa6be272103455 days 18 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0xa6bc794a19b12bebede82dc1613454642dc09245c691090bfb84e05c24a20ebd72098245 days 21 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x9797670ee6f62032a7b27f4dfedd6f6b9e6a1a2ca8e0d788ce6ae6a228d99bd572095555 days 23 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.00001301589 Ether
0x5cffe84e8b079dcccc2062acbe5cda106c73b58c5b627757b41bccb4c33d64f672092436 days 58 mins ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.00058571505 Ether
0x7fcb5b8c72d5504accf6a4c36c12a1de63187f5ea49fa24107f5b6378af5318372083366 days 6 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0xf8dccb09eacc1279e7ea0efcd27192e1afca977246012501f4f07ae3a9a0e1d272082646 days 6 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000006507945 Ether
0x4e8caec2d111b18eb5349a0be907dc129833b2036ec85e44a045b8d849f3efa272080906 days 7 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x8416a19f104518d2e7d0e541548da7937902ddc83398c811a1bcf7172f92dbda72079936 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x106d36aacb502af6ab2e981522295782faba385762f6707d8e553bcfc557c33972079836 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x373eacbadfd220cbb0788e15c215880c143b3d4954d1419aaf634768989b2cad72079796 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0xd566010e084cc6bffb5857c1642d56f715607b1ee3cf80ac64cbeaa443bd7db372079796 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0xc21b0fbaf05e0d77be29407ffba0d10931e73838c616cd6a526f8b64d743475d72079766 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x1d2797b02c593bd486f7ca4c91d5077772db24e8ed874cfad4029a6c52f0861a72078946 days 8 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0xd686872aadcfc9088b3a3f30b362637f2fd20a89024201215afee5e0067aa2ed72064226 days 17 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x93df447decd645e1c7ce7d15e0526331b92c9301510aa723241374d15c099cf972064056 days 17 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0x05e8a149c9ad1ac63157eb01ea9f32bbd29a28fc55f23362cfd8ea824ff9ffb172063836 days 17 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000001301589 Ether
0xd600ba92966708c4b82f1c533a2ed03f5c2ed0dd620808b680bce3d236959d8272059506 days 19 hrs ago0x3baa64a4401bbe18865547e916a9be8e6dd89a5a0x7b3c4d90e8af6030d66c07f8f815f9505e379d6f0.000006507945 Ether
[ Download CSV Export 
Warning: The compiled contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity), NestedArrayFunctionCallDecoder (medium-severity) Solidity Compiler Bugs.

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Verified Source Code for Contract 0xc77ceefa6960174accca0c6fdecb5dbd95042cda
Contract Name: RequestERC20
Compiler Version: v0.4.18+commit.9cf6e910
Optimization Enabled: No
Runs (Optimizer):  200


Contract Source Code
pragma solidity 0.4.18;

// From https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol
/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a * b;

    assert(a == 0 || c / a == b);
    return c;
  }

  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 c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }

  function toInt256Safe(uint256 a) internal pure returns (int256) {
    int256 b = int256(a);
    assert(b >= 0);
    return b;
  }
}

/**
 * @title SafeMathInt
 * @dev Math operations with safety checks that throw on error
 * @dev SafeMath adapted for int256
 */
library SafeMathInt {
  function mul(int256 a, int256 b) internal pure returns (int256) {
    // Prevent overflow when multiplying INT256_MIN with -1
    // https://github.com/RequestNetwork/requestNetwork/issues/43
    assert(!(a == - 2**255 && b == -1) && !(b == - 2**255 && a == -1));

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

  function div(int256 a, int256 b) internal pure returns (int256) {
    // Prevent overflow when dividing INT256_MIN by -1
    // https://github.com/RequestNetwork/requestNetwork/issues/43
    assert(!(a == - 2**255 && b == -1));

    // assert(b > 0); // Solidity automatically throws when dividing by 0
    int256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(int256 a, int256 b) internal pure returns (int256) {
    assert((b >= 0 && a - b <= a) || (b < 0 && a - b > a));

    return a - b;
  }

  function add(int256 a, int256 b) internal pure returns (int256) {
    int256 c = a + b;
    assert((b >= 0 && c >= a) || (b < 0 && c < a));
    return c;
  }

  function toUint256Safe(int256 a) internal pure returns (uint256) {
    assert(a>=0);
    return uint256(a);
  }
}

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 * @dev SafeMath adapted for uint8
 */
library SafeMathUint8 {
  function mul(uint8 a, uint8 b) internal pure returns (uint8) {
    uint8 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint8 a, uint8 b) internal pure returns (uint8) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint8 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint8 a, uint8 b) internal pure returns (uint8) {
    assert(b <= a);
    return a - b;
  }

  function add(uint8 a, uint8 b) internal pure returns (uint8) {
    uint8 c = a + b;
    assert(c >= a);
    return c;
  }
}

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 * @dev SafeMath adapted for uint96
 */
library SafeMathUint96 {
  function mul(uint96 a, uint96 b) internal pure returns (uint96) {
    uint96 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint96 a, uint96 b) internal pure returns (uint96) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint96 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint96 a, uint96 b) internal pure returns (uint96) {
    assert(b <= a);
    return a - b;
  }

  function add(uint96 a, uint96 b) internal pure returns (uint96) {
    uint96 c = a + b;
    assert(c >= a);
    return c;
  }
}

/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/179
 */
contract ERC20Basic {
  uint256 public totalSupply;
  function balanceOf(address who) public constant 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 constant 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 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 OwnershipTransferred(address indexed previousOwner, address indexed newOwner);


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  function Ownable() 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 transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) onlyOwner public {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }

}
/**
 * @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;
    Pause();
  }

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


/**
 * @title Administrable
 * @dev Base contract for the administration of Core. Handles whitelisting of currency contracts
 */
contract Administrable is Pausable {

    // mapping of address of trusted contract
    mapping(address => uint8) public trustedCurrencyContracts;

    // Events of the system
    event NewTrustedContract(address newContract);
    event RemoveTrustedContract(address oldContract);

    /**
     * @dev add a trusted currencyContract 
     *
     * @param _newContractAddress The address of the currencyContract
     */
    function adminAddTrustedCurrencyContract(address _newContractAddress)
        external
        onlyOwner
    {
        trustedCurrencyContracts[_newContractAddress] = 1; //Using int instead of boolean in case we need several states in the future.
        NewTrustedContract(_newContractAddress);
    }

    /**
     * @dev remove a trusted currencyContract 
     *
     * @param _oldTrustedContractAddress The address of the currencyContract
     */
    function adminRemoveTrustedCurrencyContract(address _oldTrustedContractAddress)
        external
        onlyOwner
    {
        require(trustedCurrencyContracts[_oldTrustedContractAddress] != 0);
        trustedCurrencyContracts[_oldTrustedContractAddress] = 0;
        RemoveTrustedContract(_oldTrustedContractAddress);
    }

    /**
     * @dev get the status of a trusted currencyContract 
     * @dev Not used today, useful if we have several states in the future.
     *
     * @param _contractAddress The address of the currencyContract
     * @return The status of the currencyContract. If trusted 1, otherwise 0
     */
    function getStatusContract(address _contractAddress)
        view
        external
        returns(uint8) 
    {
        return trustedCurrencyContracts[_contractAddress];
    }

    /**
     * @dev check if a currencyContract is trusted
     *
     * @param _contractAddress The address of the currencyContract
     * @return bool true if contract is trusted
     */
    function isTrustedContract(address _contractAddress)
        public
        view
        returns(bool)
    {
        return trustedCurrencyContracts[_contractAddress] == 1;
    }
}

/**
 * @title RequestCore
 *
 * @dev The Core is the main contract which stores all the requests.
 *
 * @dev The Core philosophy is to be as much flexible as possible to adapt in the future to any new system
 * @dev All the important conditions and an important part of the business logic takes place in the currency contracts.
 * @dev Requests can only be created in the currency contracts
 * @dev Currency contracts have to be allowed by the Core and respect the business logic.
 * @dev Request Network will develop one currency contracts per currency and anyone can creates its own currency contracts.
 */
contract RequestCore is Administrable {
    using SafeMath for uint256;
    using SafeMathUint96 for uint96;
    using SafeMathInt for int256;
    using SafeMathUint8 for uint8;

    enum State { Created, Accepted, Canceled }

    struct Request {
        // ID address of the payer
        address payer;

        // Address of the contract managing the request
        address currencyContract;

        // State of the request
        State state;

        // Main payee
        Payee payee;
    }

    // Structure for the payees. A sub payee is an additional entity which will be paid during the processing of the invoice.
    // ex: can be used for routing taxes or fees at the moment of the payment.
    struct Payee {
        // ID address of the payee
        address addr;

        // amount expected for the payee. 
        // Not uint for evolution (may need negative amounts one day), and simpler operations
        int256 expectedAmount;

        // balance of the payee
        int256 balance;
    }

    // Count of request in the mapping. A maximum of 2^96 requests can be created per Core contract.
    // Integer, incremented for each request of a Core contract, starting from 0
    // RequestId (256bits) = contract address (160bits) + numRequest
    uint96 public numRequests; 
    
    // Mapping of all the Requests. The key is the request ID.
    // not anymore public to avoid "UnimplementedFeatureError: Only in-memory reference type can be stored."
    // https://github.com/ethereum/solidity/issues/3577
    mapping(bytes32 => Request) requests;

    // Mapping of subPayees of the requests. The key is the request ID.
    // This array is outside the Request structure to optimize the gas cost when there is only 1 payee.
    mapping(bytes32 => Payee[256]) public subPayees;

    /*
     *  Events 
     */
    event Created(bytes32 indexed requestId, address indexed payee, address indexed payer, address creator, string data);
    event Accepted(bytes32 indexed requestId);
    event Canceled(bytes32 indexed requestId);

    // Event for Payee & subPayees
    event NewSubPayee(bytes32 indexed requestId, address indexed payee); // Separated from the Created Event to allow a 4th indexed parameter (subpayees)
    event UpdateExpectedAmount(bytes32 indexed requestId, uint8 payeeIndex, int256 deltaAmount);
    event UpdateBalance(bytes32 indexed requestId, uint8 payeeIndex, int256 deltaAmount);

    /*
     * @dev Function used by currency contracts to create a request in the Core
     *
     * @dev _payees and _expectedAmounts must have the same size
     *
     * @param _creator Request creator. The creator is the one who initiated the request (create or sign) and not necessarily the one who broadcasted it
     * @param _payees array of payees address (the index 0 will be the payee the others are subPayees). Size must be smaller than 256.
     * @param _expectedAmounts array of Expected amount to be received by each payees. Must be in same order than the payees. Size must be smaller than 256.
     * @param _payer Entity expected to pay
     * @param _data data of the request
     * @return Returns the id of the request
     */
    function createRequest(
        address     _creator,
        address[]   _payees,
        int256[]    _expectedAmounts,
        address     _payer,
        string      _data)
        external
        whenNotPaused 
        returns (bytes32 requestId) 
    {
        // creator must not be null
        require(_creator!=0); // not as modifier to lighten the stack
        // call must come from a trusted contract
        require(isTrustedContract(msg.sender)); // not as modifier to lighten the stack

        // Generate the requestId
        requestId = generateRequestId();

        address mainPayee;
        int256 mainExpectedAmount;
        // extract the main payee if filled
        if(_payees.length!=0) {
            mainPayee = _payees[0];
            mainExpectedAmount = _expectedAmounts[0];
        }

        // Store the new request
        requests[requestId] = Request(_payer, msg.sender, State.Created, Payee(mainPayee, mainExpectedAmount, 0));

        // Declare the new request
        Created(requestId, mainPayee, _payer, _creator, _data);
        
        // Store and declare the sub payees (needed in internal function to avoid "stack too deep")
        initSubPayees(requestId, _payees, _expectedAmounts);

        return requestId;
    }

    /*
     * @dev Function used by currency contracts to create a request in the Core from bytes
     * @dev Used to avoid receiving a stack too deep error when called from a currency contract with too many parameters.
     * @audit Note that to optimize the stack size and the gas cost we do not extract the params and store them in the stack. As a result there is some code redundancy
     * @param _data bytes containing all the data packed :
            address(creator)
            address(payer)
            uint8(number_of_payees)
            [
                address(main_payee_address)
                int256(main_payee_expected_amount)
                address(second_payee_address)
                int256(second_payee_expected_amount)
                ...
            ]
            uint8(data_string_size)
            size(data)
     * @return Returns the id of the request 
     */ 
    function createRequestFromBytes(bytes _data) 
        external
        whenNotPaused 
        returns (bytes32 requestId) 
    {
        // call must come from a trusted contract
        require(isTrustedContract(msg.sender)); // not as modifier to lighten the stack

        // extract address creator & payer
        address creator = extractAddress(_data, 0);

        address payer = extractAddress(_data, 20);

        // creator must not be null
        require(creator!=0);
        
        // extract the number of payees
        uint8 payeesCount = uint8(_data[40]);

        // get the position of the dataSize in the byte (= number_of_payees * (address_payee_size + int256_payee_size) + address_creator_size + address_payer_size + payees_count_size
        //                                              (= number_of_payees * (20+32) + 20 + 20 + 1 )
        uint256 offsetDataSize = uint256(payeesCount).mul(52).add(41);

        // extract the data size and then the data itself
        uint8 dataSize = uint8(_data[offsetDataSize]);
        string memory dataStr = extractString(_data, dataSize, offsetDataSize.add(1));

        address mainPayee;
        int256 mainExpectedAmount;
        // extract the main payee if possible
        if(payeesCount!=0) {
            mainPayee = extractAddress(_data, 41);
            mainExpectedAmount = int256(extractBytes32(_data, 61));
        }

        // Generate the requestId
        requestId = generateRequestId();

        // Store the new request
        requests[requestId] = Request(payer, msg.sender, State.Created, Payee(mainPayee, mainExpectedAmount, 0));

        // Declare the new request
        Created(requestId, mainPayee, payer, creator, dataStr);

        // Store and declare the sub payees
        for(uint8 i = 1; i < payeesCount; i = i.add(1)) {
            address subPayeeAddress = extractAddress(_data, uint256(i).mul(52).add(41));

            // payees address cannot be 0x0
            require(subPayeeAddress != 0);

            subPayees[requestId][i-1] =  Payee(subPayeeAddress, int256(extractBytes32(_data, uint256(i).mul(52).add(61))), 0);
            NewSubPayee(requestId, subPayeeAddress);
        }

        return requestId;
    }

    /*
     * @dev Function used by currency contracts to accept a request in the Core.
     * @dev callable only by the currency contract of the request
     * @param _requestId Request id
     */ 
    function accept(bytes32 _requestId) 
        external
    {
        Request storage r = requests[_requestId];
        require(r.currencyContract==msg.sender); 
        r.state = State.Accepted;
        Accepted(_requestId);
    }

    /*
     * @dev Function used by currency contracts to cancel a request in the Core. Several reasons can lead to cancel a request, see request life cycle for more info.
     * @dev callable only by the currency contract of the request
     * @param _requestId Request id
     */ 
    function cancel(bytes32 _requestId)
        external
    {
        Request storage r = requests[_requestId];
        require(r.currencyContract==msg.sender);
        r.state = State.Canceled;
        Canceled(_requestId);
    }   

    /*
     * @dev Function used to update the balance
     * @dev callable only by the currency contract of the request
     * @param _requestId Request id
     * @param _payeeIndex index of the payee (0 = main payee)
     * @param _deltaAmount modifier amount
     */ 
    function updateBalance(bytes32 _requestId, uint8 _payeeIndex, int256 _deltaAmount)
        external
    {   
        Request storage r = requests[_requestId];
        require(r.currencyContract==msg.sender);

        if( _payeeIndex == 0 ) {
            // modify the main payee
            r.payee.balance = r.payee.balance.add(_deltaAmount);
        } else {
            // modify the sub payee
            Payee storage sp = subPayees[_requestId][_payeeIndex-1];
            sp.balance = sp.balance.add(_deltaAmount);
        }
        UpdateBalance(_requestId, _payeeIndex, _deltaAmount);
    }

    /*
     * @dev Function update the expectedAmount adding additional or subtract
     * @dev callable only by the currency contract of the request
     * @param _requestId Request id
     * @param _payeeIndex index of the payee (0 = main payee)
     * @param _deltaAmount modifier amount
     */ 
    function updateExpectedAmount(bytes32 _requestId, uint8 _payeeIndex, int256 _deltaAmount)
        external
    {   
        Request storage r = requests[_requestId];
        require(r.currencyContract==msg.sender); 

        if( _payeeIndex == 0 ) {
            // modify the main payee
            r.payee.expectedAmount = r.payee.expectedAmount.add(_deltaAmount);    
        } else {
            // modify the sub payee
            Payee storage sp = subPayees[_requestId][_payeeIndex-1];
            sp.expectedAmount = sp.expectedAmount.add(_deltaAmount);
        }
        UpdateExpectedAmount(_requestId, _payeeIndex, _deltaAmount);
    }

    /*
     * @dev Internal: Init payees for a request (needed to avoid 'stack too deep' in createRequest())
     * @param _requestId Request id
     * @param _payees array of payees address
     * @param _expectedAmounts array of payees initial expected amounts
     */ 
    function initSubPayees(bytes32 _requestId, address[] _payees, int256[] _expectedAmounts)
        internal
    {
        require(_payees.length == _expectedAmounts.length);
     
        for (uint8 i = 1; i < _payees.length; i = i.add(1))
        {
            // payees address cannot be 0x0
            require(_payees[i] != 0);
            subPayees[_requestId][i-1] = Payee(_payees[i], _expectedAmounts[i], 0);
            NewSubPayee(_requestId, _payees[i]);
        }
    }


    /* GETTER */
    /*
     * @dev Get address of a payee
     * @param _requestId Request id
     * @param _payeeIndex payee index (0 = main payee)
     * @return payee address
     */ 
    function getPayeeAddress(bytes32 _requestId, uint8 _payeeIndex)
        public
        constant
        returns(address)
    {
        if(_payeeIndex == 0) {
            return requests[_requestId].payee.addr;
        } else {
            return subPayees[_requestId][_payeeIndex-1].addr;
        }
    }

    /*
     * @dev Get payer of a request
     * @param _requestId Request id
     * @return payer address
     */ 
    function getPayer(bytes32 _requestId)
        public
        constant
        returns(address)
    {
        return requests[_requestId].payer;
    }

    /*
     * @dev Get amount expected of a payee
     * @param _requestId Request id
     * @param _payeeIndex payee index (0 = main payee)
     * @return amount expected
     */     
    function getPayeeExpectedAmount(bytes32 _requestId, uint8 _payeeIndex)
        public
        constant
        returns(int256)
    {
        if(_payeeIndex == 0) {
            return requests[_requestId].payee.expectedAmount;
        } else {
            return subPayees[_requestId][_payeeIndex-1].expectedAmount;
        }
    }

    /*
     * @dev Get number of subPayees for a request
     * @param _requestId Request id
     * @return number of subPayees
     */     
    function getSubPayeesCount(bytes32 _requestId)
        public
        constant
        returns(uint8)
    {
        for (uint8 i = 0; subPayees[_requestId][i].addr != address(0); i = i.add(1)) {
            // nothing to do
        }
        return i;
    }

    /*
     * @dev Get currencyContract of a request
     * @param _requestId Request id
     * @return currencyContract address
     */
    function getCurrencyContract(bytes32 _requestId)
        public
        constant
        returns(address)
    {
        return requests[_requestId].currencyContract;
    }

    /*
     * @dev Get balance of a payee
     * @param _requestId Request id
     * @param _payeeIndex payee index (0 = main payee)
     * @return balance
     */     
    function getPayeeBalance(bytes32 _requestId, uint8 _payeeIndex)
        public
        constant
        returns(int256)
    {
        if(_payeeIndex == 0) {
            return requests[_requestId].payee.balance;    
        } else {
            return subPayees[_requestId][_payeeIndex-1].balance;
        }
    }

    /*
     * @dev Get balance total of a request
     * @param _requestId Request id
     * @return balance
     */     
    function getBalance(bytes32 _requestId)
        public
        constant
        returns(int256)
    {
        int256 balance = requests[_requestId].payee.balance;

        for (uint8 i = 0; subPayees[_requestId][i].addr != address(0); i = i.add(1))
        {
            balance = balance.add(subPayees[_requestId][i].balance);
        }

        return balance;
    }


    /*
     * @dev check if all the payees balances are null
     * @param _requestId Request id
     * @return true if all the payees balances are equals to 0
     */     
    function areAllBalanceNull(bytes32 _requestId)
        public
        constant
        returns(bool isNull)
    {
        isNull = requests[_requestId].payee.balance == 0;

        for (uint8 i = 0; isNull && subPayees[_requestId][i].addr != address(0); i = i.add(1))
        {
            isNull = subPayees[_requestId][i].balance == 0;
        }

        return isNull;
    }

    /*
     * @dev Get total expectedAmount of a request
     * @param _requestId Request id
     * @return balance
     */     
    function getExpectedAmount(bytes32 _requestId)
        public
        constant
        returns(int256)
    {
        int256 expectedAmount = requests[_requestId].payee.expectedAmount;

        for (uint8 i = 0; subPayees[_requestId][i].addr != address(0); i = i.add(1))
        {
            expectedAmount = expectedAmount.add(subPayees[_requestId][i].expectedAmount);
        }

        return expectedAmount;
    }

    /*
     * @dev Get state of a request
     * @param _requestId Request id
     * @return state
     */ 
    function getState(bytes32 _requestId)
        public
        constant
        returns(State)
    {
        return requests[_requestId].state;
    }

    /*
     * @dev Get address of a payee
     * @param _requestId Request id
     * @return payee index (0 = main payee) or -1 if not address not found
     */
    function getPayeeIndex(bytes32 _requestId, address _address)
        public
        constant
        returns(int16)
    {
        // return 0 if main payee
        if(requests[_requestId].payee.addr == _address) return 0;

        for (uint8 i = 0; subPayees[_requestId][i].addr != address(0); i = i.add(1))
        {
            if(subPayees[_requestId][i].addr == _address) {
                // if found return subPayee index + 1 (0 is main payee)
                return i+1;
            }
        }
        return -1;
    }

    /*
     * @dev getter of a request
     * @param _requestId Request id
     * @return request as a tuple : (address payer, address currencyContract, State state, address payeeAddr, int256 payeeExpectedAmount, int256 payeeBalance)
     */ 
    function getRequest(bytes32 _requestId) 
        external
        constant
        returns(address payer, address currencyContract, State state, address payeeAddr, int256 payeeExpectedAmount, int256 payeeBalance)
    {
        Request storage r = requests[_requestId];
        return ( r.payer, 
                 r.currencyContract, 
                 r.state, 
                 r.payee.addr, 
                 r.payee.expectedAmount, 
                 r.payee.balance );
    }

    /*
     * @dev extract a string from a bytes. Extracts a sub-part from tha bytes and convert it to string
     * @param data bytes from where the string will be extracted
     * @param size string size to extract
     * @param _offset position of the first byte of the string in bytes
     * @return string
     */ 
    function extractString(bytes data, uint8 size, uint _offset) 
        internal 
        pure 
        returns (string) 
    {
        bytes memory bytesString = new bytes(size);
        for (uint j = 0; j < size; j++) {
            bytesString[j] = data[_offset+j];
        }
        return string(bytesString);
    }

    /*
     * @dev generate a new unique requestId
     * @return a bytes32 requestId 
     */ 
    function generateRequestId()
        internal
        returns (bytes32)
    {
        // Update numRequest
        numRequests = numRequests.add(1);
        // requestId = ADDRESS_CONTRACT_CORE + numRequests (0xADRRESSCONTRACT00000NUMREQUEST)
        return bytes32((uint256(this) << 96).add(numRequests));
    }

    /*
     * @dev extract an address from a bytes at a given position
     * @param _data bytes from where the address will be extract
     * @param _offset position of the first byte of the address
     * @return address
     */
    function extractAddress(bytes _data, uint offset)
        internal
        pure
        returns (address m)
    {
        require(offset >=0 && offset + 20 <= _data.length);
        assembly {
            m := and( mload(add(_data, add(20, offset))), 
                      0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        }
    }

    /*
     * @dev extract a bytes32 from a bytes
     * @param data bytes from where the bytes32 will be extract
     * @param offset position of the first byte of the bytes32
     * @return address
     */
    function extractBytes32(bytes _data, uint offset)
        public
        pure
        returns (bytes32 bs)
    {
        require(offset >=0 && offset + 32 <= _data.length);
        assembly {
            bs := mload(add(_data, add(32, offset)))
        }
    }

    /**
     * @dev transfer to owner any tokens send by mistake on this contracts
     * @param token The address of the token to transfer.
     * @param amount The amount to be transfered.
     */
    function emergencyERC20Drain(ERC20 token, uint amount )
        public
        onlyOwner 
    {
        token.transfer(owner, amount);
    }
}

/**
 * @title RequestCollectInterface
 *
 * @dev RequestCollectInterface is a contract managing the fees for currency contracts
 */
contract RequestCollectInterface is Pausable {
    using SafeMath for uint256;

    uint256 public rateFeesNumerator;
    uint256 public rateFeesDenominator;
    uint256 public maxFees;

    // address of the contract that will burn req token (through Kyber)
    address public requestBurnerContract;

    /*
     *  Events 
     */
    event UpdateRateFees(uint256 rateFeesNumerator, uint256 rateFeesDenominator);
    event UpdateMaxFees(uint256 maxFees);

    /*
     * @dev Constructor
     * @param _requestBurnerContract Address of the contract where to send the ethers. 
     * This burner contract will have a function that can be called by anyone and will exchange ethers to req via Kyber and burn the REQ
     */  
    function RequestCollectInterface(address _requestBurnerContract) 
        public
    {
        requestBurnerContract = _requestBurnerContract;
    }

    /*
     * @dev send fees to the request burning address
     * @param _amount amount to send to the burning address
     */  
    function collectForREQBurning(uint256 _amount)
        internal
        returns(bool)
    {
        return requestBurnerContract.send(_amount);
    }

    /*
     * @dev compute the fees
     * @param _expectedAmount amount expected for the request
     * @return the expected amount of fees in wei
     */  
    function collectEstimation(int256 _expectedAmount)
        public
        view
        returns(uint256)
    {
        if(_expectedAmount<0) return 0;

        uint256 computedCollect = uint256(_expectedAmount).mul(rateFeesNumerator);

        if(rateFeesDenominator != 0) {
            computedCollect = computedCollect.div(rateFeesDenominator);
        }

        return computedCollect < maxFees ? computedCollect : maxFees;
    }

    /*
     * @dev set the fees rate
     * NB: if the _rateFeesDenominator is 0, it will be treated as 1. (in other words, the computation of the fees will not use it)
     * @param _rateFeesNumerator        numerator rate
     * @param _rateFeesDenominator      denominator rate
     */  
    function setRateFees(uint256 _rateFeesNumerator, uint256 _rateFeesDenominator)
        external
        onlyOwner
    {
        rateFeesNumerator = _rateFeesNumerator;
        rateFeesDenominator = _rateFeesDenominator;
        UpdateRateFees(rateFeesNumerator, rateFeesDenominator);
    }

    /*
     * @dev set the maximum fees in wei
     * @param _newMax new max
     */  
    function setMaxCollectable(uint256 _newMaxFees) 
        external
        onlyOwner
    {
        maxFees = _newMaxFees;
        UpdateMaxFees(maxFees);
    }

    /*
     * @dev set the request burner address
     * @param _requestBurnerContract address of the contract that will burn req token (probably through Kyber)
     */  
    function setRequestBurnerContract(address _requestBurnerContract) 
        external
        onlyOwner
    {
        requestBurnerContract=_requestBurnerContract;
    }

}

/**
 * @title RequestCurrencyContractInterface
 *
 * @dev RequestCurrencyContractInterface is the currency contract managing the request in Ethereum
 * @dev The contract can be paused. In this case, nobody can create Requests anymore but people can still interact with them or withdraw funds.
 *
 * @dev Requests can be created by the Payee with createRequestAsPayee(), by the payer with createRequestAsPayer() or by the payer from a request signed offchain by the payee with broadcastSignedRequestAsPayer
 */
contract RequestCurrencyContractInterface is RequestCollectInterface {
    using SafeMath for uint256;
    using SafeMathInt for int256;
    using SafeMathUint8 for uint8;

    // RequestCore object
    RequestCore public requestCore;

    /*
     * @dev Constructor
     * @param _requestCoreAddress Request Core address
     */
    function RequestCurrencyContractInterface(address _requestCoreAddress, address _addressBurner) 
        RequestCollectInterface(_addressBurner)
        public
    {
        requestCore=RequestCore(_requestCoreAddress);
    }

    /*
     * @dev Base function for request creation
     *
     * @dev msg.sender will be the creator
     *
     * @param _payer Entity expected to pay
     * @param _payeesIdAddress array of payees address (the index 0 will be the payee - must be msg.sender - the others are subPayees)
     * @param _expectedAmounts array of Expected amount to be received by each payees
     * @param _data Hash linking to additional data on the Request stored on IPFS
     *
     * @return Returns the id of the request and the sum of the expected amounts
     */
    function createCoreRequestInternal(
        address     _payer,
        address[]   _payeesIdAddress,
        int256[]    _expectedAmounts,
        string      _data)
        internal
        whenNotPaused
        returns(bytes32 requestId, int256 totalExpectedAmounts)
    {
        totalExpectedAmounts = 0;
        for (uint8 i = 0; i < _expectedAmounts.length; i = i.add(1))
        {
            // all expected amounts must be positive
            require(_expectedAmounts[i]>=0);
            // compute the total expected amount of the request
            totalExpectedAmounts = totalExpectedAmounts.add(_expectedAmounts[i]);
        }

        // store request in the core
        requestId= requestCore.createRequest(msg.sender, _payeesIdAddress, _expectedAmounts, _payer, _data);
    }

    /*
     * @dev Function to accept a request
     *
     * @dev msg.sender must be _payer
     *
     * @param _requestId id of the request
     */
    function acceptAction(bytes32 _requestId)
        public
        whenNotPaused
        onlyRequestPayer(_requestId)
    {
        // only a created request can be accepted
        require(requestCore.getState(_requestId)==RequestCore.State.Created);

        // declare the acceptation in the core
        requestCore.accept(_requestId);
    }


    /*
     * @dev Function to cancel a request
     *
     * @dev msg.sender must be the _payer or the _payee.
     * @dev only request with balance equals to zero can be cancel
     *
     * @param _requestId id of the request
     */
    function cancelAction(bytes32 _requestId)
        public
        whenNotPaused
    {
        // payer can cancel if request is just created
        // payee can cancel when request is not canceled yet
        require((requestCore.getPayer(_requestId)==msg.sender && requestCore.getState(_requestId)==RequestCore.State.Created)
                || (requestCore.getPayeeAddress(_requestId,0)==msg.sender && requestCore.getState(_requestId)!=RequestCore.State.Canceled));

        // impossible to cancel a Request with any payees balance != 0
        require(requestCore.areAllBalanceNull(_requestId));

        // declare the cancellation in the core
        requestCore.cancel(_requestId);
    }


    /*
     * @dev Function to declare additionals
     *
     * @dev msg.sender must be _payer
     * @dev the request must be accepted or created
     *
     * @param _requestId id of the request
     * @param _additionalAmounts amounts of additional to declare (index 0 is for main payee)
     */
    function additionalAction(bytes32 _requestId, uint256[] _additionalAmounts)
        public
        whenNotPaused
        onlyRequestPayer(_requestId)
    {

        // impossible to make additional if request is canceled
        require(requestCore.getState(_requestId)!=RequestCore.State.Canceled);

        // impossible to declare more additionals than the number of payees
        require(_additionalAmounts.length <= requestCore.getSubPayeesCount(_requestId).add(1));

        for(uint8 i = 0; i < _additionalAmounts.length; i = i.add(1)) {
            // no need to declare a zero as additional 
            if(_additionalAmounts[i] != 0) {
                // Store and declare the additional in the core
                requestCore.updateExpectedAmount(_requestId, i, _additionalAmounts[i].toInt256Safe());
            }
        }
    }

    /*
     * @dev Function to declare subtracts
     *
     * @dev msg.sender must be _payee
     * @dev the request must be accepted or created
     *
     * @param _requestId id of the request
     * @param _subtractAmounts amounts of subtract to declare (index 0 is for main payee)
     */
    function subtractAction(bytes32 _requestId, uint256[] _subtractAmounts)
        public
        whenNotPaused
        onlyRequestPayee(_requestId)
    {
        // impossible to make subtracts if request is canceled
        require(requestCore.getState(_requestId)!=RequestCore.State.Canceled);

        // impossible to declare more subtracts than the number of payees
        require(_subtractAmounts.length <= requestCore.getSubPayeesCount(_requestId).add(1));

        for(uint8 i = 0; i < _subtractAmounts.length; i = i.add(1)) {
            // no need to declare a zero as subtracts 
            if(_subtractAmounts[i] != 0) {
                // subtract must be equal or lower than amount expected
                require(requestCore.getPayeeExpectedAmount(_requestId,i) >= _subtractAmounts[i].toInt256Safe());
                // Store and declare the subtract in the core
                requestCore.updateExpectedAmount(_requestId, i, -_subtractAmounts[i].toInt256Safe());
            }
        }
    }
    // ----------------------------------------------------------------------------------------

    /*
     * @dev Modifier to check if msg.sender is the main payee
     * @dev Revert if msg.sender is not the main payee
     * @param _requestId id of the request
     */ 
    modifier onlyRequestPayee(bytes32 _requestId)
    {
        require(requestCore.getPayeeAddress(_requestId, 0)==msg.sender);
        _;
    }

    /*
     * @dev Modifier to check if msg.sender is payer
     * @dev Revert if msg.sender is not payer
     * @param _requestId id of the request
     */ 
    modifier onlyRequestPayer(bytes32 _requestId)
    {
        require(requestCore.getPayer(_requestId)==msg.sender);
        _;
    }
}


/**
 * @title RequestERC20
 *
 * @dev RequestERC20 is the currency contract managing the request in ERC20 token
 * @dev The contract can be paused. In this case, nobody can create Requests anymore but people can still interact with them or withdraw funds.
 *
 * @dev Requests can be created by the Payee with createRequestAsPayee(), by the payer with createRequestAsPayer() or by the payer from a request signed offchain by the payee with broadcastSignedRequestAsPayer
 */
contract RequestERC20 is RequestCurrencyContractInterface {
    using SafeMath for uint256;
    using SafeMathInt for int256;
    using SafeMathUint8 for uint8;

    // payment addresses by requestId (optional). We separate the Identity of the payee/payer (in the core) and the wallet address in the currency contract
    mapping(bytes32 => address[256]) public payeesPaymentAddress;
    mapping(bytes32 => address) public payerRefundAddress;

    // token address
    ERC20 public erc20Token;

    /*
     * @dev Constructor
     * @param _requestCoreAddress Request Core address
     * @param _requestBurnerAddress Request Burner contract address
     * @param _erc20Token ERC20 token contract handled by this currency contract
     */
    function RequestERC20(address _requestCoreAddress, address _requestBurnerAddress, ERC20 _erc20Token) 
        RequestCurrencyContractInterface(_requestCoreAddress, _requestBurnerAddress)
        public
    {
        erc20Token = _erc20Token;
    }

    /*
     * @dev Function to create a request as payee
     *
     * @dev msg.sender must be the main payee
     * @dev if _payeesPaymentAddress.length > _payeesIdAddress.length, the extra addresses will be stored but never used
     *
     * @param _payeesIdAddress array of payees address (the index 0 will be the payee - must be msg.sender - the others are subPayees)
     * @param _payeesPaymentAddress array of payees address for payment (optional)
     * @param _expectedAmounts array of Expected amount to be received by each payees
     * @param _payer Entity expected to pay
     * @param _payerRefundAddress Address of refund for the payer (optional)
     * @param _data Hash linking to additional data on the Request stored on IPFS
     *
     * @return Returns the id of the request
     */
    function createRequestAsPayeeAction(
        address[]   _payeesIdAddress,
        address[]   _payeesPaymentAddress,
        int256[]    _expectedAmounts,
        address     _payer,
        address     _payerRefundAddress,
        string      _data)
        external
        payable
        whenNotPaused
        returns(bytes32 requestId)
    {
        require(msg.sender == _payeesIdAddress[0] && msg.sender != _payer && _payer != 0);

        int256 totalExpectedAmounts;
        (requestId, totalExpectedAmounts) = createCoreRequestInternal(_payer, _payeesIdAddress, _expectedAmounts, _data);
        
        // compute and send fees
        uint256 fees = collectEstimation(totalExpectedAmounts);
        require(fees == msg.value && collectForREQBurning(fees));

        // set payment addresses for payees
        for (uint8 j = 0; j < _payeesPaymentAddress.length; j = j.add(1)) {
            payeesPaymentAddress[requestId][j] = _payeesPaymentAddress[j];
        }
        // set payment address for payer
        if(_payerRefundAddress != 0) {
            payerRefundAddress[requestId] = _payerRefundAddress;
        }

        return requestId;
    }


    /*
     * @dev Function to create a request as payer. The request is payed if _payeeAmounts > 0.
     *
     * @dev msg.sender will be the payer
     * @dev If a contract is given as a payee make sure it is payable. Otherwise, the request will not be payable.
     *
     * @param _payeesIdAddress array of payees address (the index 0 will be the payee the others are subPayees)
     * @param _expectedAmounts array of Expected amount to be received by each payees
     * @param _payerRefundAddress Address of refund for the payer (optional)
     * @param _payeeAmounts array of amount repartition for the payment
     * @param _additionals array to increase the ExpectedAmount for payees
     * @param _data Hash linking to additional data on the Request stored on IPFS
     *
     * @return Returns the id of the request
     */
    function createRequestAsPayerAction(
        address[]   _payeesIdAddress,
        int256[]    _expectedAmounts,
        address     _payerRefundAddress,
        uint256[]   _payeeAmounts,
        uint256[]   _additionals,
        string      _data)
        external
        payable
        whenNotPaused
        returns(bytes32 requestId)
    {
        require(msg.sender != _payeesIdAddress[0] && _payeesIdAddress[0] != 0);

        int256 totalExpectedAmounts;
        (requestId, totalExpectedAmounts) = createCoreRequestInternal(msg.sender, _payeesIdAddress, _expectedAmounts, _data);

        // set payment address for payer
        if(_payerRefundAddress != 0) {
            payerRefundAddress[requestId] = _payerRefundAddress;
        }

        // accept and pay the request with the value remaining after the fee collect
        acceptAndPay(requestId, _payeeAmounts, _additionals, totalExpectedAmounts);

        return requestId;
    }

    /*
     * @dev Function to broadcast and accept an offchain signed request (the broadcaster can also pays and makes additionals )
     *
     * @dev msg.sender will be the _payer
     * @dev only the _payer can make additionals
     * @dev if _payeesPaymentAddress.length > _requestData.payeesIdAddress.length, the extra addresses will be stored but never used
     *
     * @param _requestData nasty bytes containing : creator, payer, payees|expectedAmounts, data
     * @param _payeesPaymentAddress array of payees address for payment (optional) 
     * @param _payeeAmounts array of amount repartition for the payment
     * @param _additionals array to increase the ExpectedAmount for payees
     * @param _expirationDate timestamp after that the signed request cannot be broadcasted
     * @param _signature ECDSA signature in bytes
     *
     * @return Returns the id of the request
     */
    function broadcastSignedRequestAsPayerAction(
        bytes       _requestData, // gather data to avoid "stack too deep"
        address[]   _payeesPaymentAddress,
        uint256[]   _payeeAmounts,
        uint256[]   _additionals,
        uint256     _expirationDate,
        bytes       _signature)
        external
        payable
        whenNotPaused
        returns(bytes32 requestId)
    {
        // check expiration date
        require(_expirationDate >= block.timestamp);

        // check the signature
        require(checkRequestSignature(_requestData, _payeesPaymentAddress, _expirationDate, _signature));

        return createAcceptAndPayFromBytes(_requestData, _payeesPaymentAddress, _payeeAmounts, _additionals);
    }

    /*
     * @dev Internal function to create, accept, add additionals and pay a request as Payer
     *
     * @dev msg.sender must be _payer
     *
     * @param _requestData nasty bytes containing : creator, payer, payees|expectedAmounts, data
     * @param _payeesPaymentAddress array of payees address for payment (optional)
     * @param _payeeAmounts array of amount repartition for the payment
     * @param _additionals Will increase the ExpectedAmount of the request right after its creation by adding additionals
     *
     * @return Returns the id of the request
     */
    function createAcceptAndPayFromBytes(
        bytes       _requestData,
        address[]   _payeesPaymentAddress,
        uint256[]   _payeeAmounts,
        uint256[]   _additionals)
        internal
        returns(bytes32 requestId)
    {
        // extract main payee
        address mainPayee = extractAddress(_requestData, 41);
        require(msg.sender != mainPayee && mainPayee != 0);
        // creator must be the main payee
        require(extractAddress(_requestData, 0) == mainPayee);

        // extract the number of payees
        uint8 payeesCount = uint8(_requestData[40]);
        int256 totalExpectedAmounts = 0;
        for(uint8 i = 0; i < payeesCount; i++) {
            // extract the expectedAmount for the payee[i]
            int256 expectedAmountTemp = int256(extractBytes32(_requestData, uint256(i).mul(52).add(61)));
            // compute the total expected amount of the request
            totalExpectedAmounts = totalExpectedAmounts.add(expectedAmountTemp);
            // all expected amount must be positive
            require(expectedAmountTemp>0);
        }

        // compute and send fees
        uint256 fees = collectEstimation(totalExpectedAmounts);
        // check fees has been well received
        require(fees == msg.value && collectForREQBurning(fees));

        // insert the msg.sender as the payer in the bytes
        updateBytes20inBytes(_requestData, 20, bytes20(msg.sender));
        // store request in the core
        requestId = requestCore.createRequestFromBytes(_requestData);
        
        // set payment addresses for payees
        for (uint8 j = 0; j < _payeesPaymentAddress.length; j = j.add(1)) {
            payeesPaymentAddress[requestId][j] = _payeesPaymentAddress[j];
        }

        // accept and pay the request with the value remaining after the fee collect
        acceptAndPay(requestId, _payeeAmounts, _additionals, totalExpectedAmounts);

        return requestId;
    }

    /*
     * @dev Internal function to accept, add additionals and pay a request as Payer
     *
     * @param _requestId id of the request
     * @param _payeesAmounts Amount to pay to payees (sum must be equals to _amountPaid)
     * @param _additionals Will increase the ExpectedAmounts of payees
     * @param _payeeAmountsSum total of amount token send for this transaction
     *
     */ 
    function acceptAndPay(
        bytes32 _requestId,
        uint256[] _payeeAmounts,
        uint256[] _additionals,
        int256 _payeeAmountsSum)
        internal
    {
        acceptAction(_requestId);
        
        additionalAction(_requestId, _additionals);

        if(_payeeAmountsSum > 0) {
            paymentInternal(_requestId, _payeeAmounts);
        }
    }

    /*
     * @dev Function to pay a request in ERC20 token
     *
     * @dev msg.sender must have a balance of the token higher or equal to the sum of _payeeAmounts
     * @dev msg.sender must have approved an amount of the token higher or equal to the sum of _payeeAmounts to the current contract
     * @dev the request will be automatically accepted if msg.sender==payer. 
     *
     * @param _requestId id of the request
     * @param _payeeAmounts Amount to pay to payees (sum must be equal to msg.value) in wei
     * @param _additionalAmounts amount of additionals per payee in wei to declare
     */
    function paymentAction(
        bytes32 _requestId,
        uint256[] _payeeAmounts,
        uint256[] _additionalAmounts)
        external
        whenNotPaused
    {
        // automatically accept request if request is created and msg.sender is payer
        if (requestCore.getState(_requestId)==RequestCore.State.Created && msg.sender == requestCore.getPayer(_requestId)) {
            acceptAction(_requestId);
        }

        if (_additionalAmounts.length != 0) {
            additionalAction(_requestId, _additionalAmounts);
        }

        paymentInternal(_requestId, _payeeAmounts);
    }


    /*
     * @dev Function to pay back in ERC20 token a request to the payees
     *
     * @dev msg.sender must have a balance of the token higher or equal to _amountToRefund
     * @dev msg.sender must have approved an amount of the token higher or equal to _amountToRefund to the current contract
     * @dev msg.sender must be one of the payees or one of the payees payment address
     * @dev the request must be created or accepted
     *
     * @param _requestId id of the request
     */
    function refundAction(bytes32 _requestId, uint256 _amountToRefund)
        external
        whenNotPaused
    {
        refundInternal(_requestId, msg.sender, _amountToRefund);
    }


    // ---- INTERNAL FUNCTIONS ----------------------------------------------------------------
    /*
     * @dev Function internal to manage payment declaration
     *
     * @param _requestId id of the request
     * @param _payeesAmounts Amount to pay to payees (sum must be equals to msg.value)
     */
    function paymentInternal(
        bytes32     _requestId,
        uint256[]   _payeeAmounts)
        internal
    {
        require(requestCore.getState(_requestId)!=RequestCore.State.Canceled);

        // we cannot have more amounts declared than actual payees
        require(_payeeAmounts.length <= requestCore.getSubPayeesCount(_requestId).add(1));

        for(uint8 i = 0; i < _payeeAmounts.length; i = i.add(1)) {
            if(_payeeAmounts[i] != 0) {
                // Store and declare the payment to the core
                requestCore.updateBalance(_requestId, i, _payeeAmounts[i].toInt256Safe());

                // pay the payment address if given, the id address otherwise
                address addressToPay;
                if(payeesPaymentAddress[_requestId][i] == 0) {
                    addressToPay = requestCore.getPayeeAddress(_requestId, i);
                } else {
                    addressToPay = payeesPaymentAddress[_requestId][i];
                }

                // payment done, the token need to be sent
                fundOrderInternal(msg.sender, addressToPay, _payeeAmounts[i]);
            }
        }
    }


    /*
     * @dev Function internal to manage refund declaration
     *
     * @param _requestId id of the request
     * @param _address address from where the refund has been done
     * @param _amount amount of the refund in ERC20 token to declare
     */
    function refundInternal(
        bytes32 _requestId,
        address _address,
        uint256 _amount)
        internal
    {
        require(requestCore.getState(_requestId)!=RequestCore.State.Canceled);

        // Check if the _address is a payeesId
        int16 payeeIndex = requestCore.getPayeeIndex(_requestId, _address);

        // get the number of payees
        uint8 payeesCount = requestCore.getSubPayeesCount(_requestId).add(1);

        if(payeeIndex < 0) {
            // if not ID addresses maybe in the payee payments addresses
            for (uint8 i = 0; i < payeesCount && payeeIndex == -1; i = i.add(1))
            {
                if(payeesPaymentAddress[_requestId][i] == _address) {
                    // get the payeeIndex
                    payeeIndex = int16(i);
                }
            }
        }
        // the address must be found somewhere
        require(payeeIndex >= 0); 

        // useless (subPayee size <256): require(payeeIndex < 265);
        requestCore.updateBalance(_requestId, uint8(payeeIndex), -_amount.toInt256Safe());

        // refund to the payment address if given, the id address otherwise
        address addressToPay = payerRefundAddress[_requestId];
        if(addressToPay == 0) {
            addressToPay = requestCore.getPayer(_requestId);
        }

        // refund declared, the money is ready to be sent to the payer
        fundOrderInternal(_address, addressToPay, _amount);
    }

    /*
     * @dev Function internal to manage fund mouvement
     *
     * @param _from address where the token will get from
     * @param _recipient address where the token has to be sent to
     * @param _amount amount in ERC20 token to send
     */
    function fundOrderInternal(
        address _from,
        address _recipient,
        uint256 _amount)
        internal
    {   
        require(erc20Token.transferFrom(_from, _recipient, _amount));
    }
    // -----------------------------------------------------------------------------

    /*
     * @dev Check the validity of a signed request & the expiration date
     * @param _data bytes containing all the data packed :
            address(creator)
            address(payer)
            uint8(number_of_payees)
            [
                address(main_payee_address)
                int256(main_payee_expected_amount)
                address(second_payee_address)
                int256(second_payee_expected_amount)
                ...
            ]
            uint8(data_string_size)
            size(data)
     * @param _payeesPaymentAddress array of payees payment addresses (the index 0 will be the payee the others are subPayees)
     * @param _expirationDate timestamp after that the signed request cannot be broadcasted
     * @param _signature ECDSA signature containing v, r and s as bytes
     *
     * @return Validity of order signature.
     */ 
    function checkRequestSignature(
        bytes       _requestData,
        address[]   _payeesPaymentAddress,
        uint256     _expirationDate,
        bytes       _signature)
        public
        view
        returns (bool)
    {
        bytes32 hash = getRequestHash(_requestData, _payeesPaymentAddress, _expirationDate);

        // extract "v, r, s" from the signature
        uint8 v = uint8(_signature[64]);
        v = v < 27 ? v.add(27) : v;
        bytes32 r = extractBytes32(_signature, 0);
        bytes32 s = extractBytes32(_signature, 32);

        // check signature of the hash with the creator address
        return isValidSignature(extractAddress(_requestData, 0), hash, v, r, s);
    }

    /*
     * @dev Function internal to calculate Keccak-256 hash of a request with specified parameters
     *
     * @param _data bytes containing all the data packed
     * @param _payeesPaymentAddress array of payees payment addresses
     * @param _expirationDate timestamp after what the signed request cannot be broadcasted
     *
     * @return Keccak-256 hash of (this,_requestData, _payeesPaymentAddress, _expirationDate)
     */
    function getRequestHash(
        bytes       _requestData,
        address[]   _payeesPaymentAddress,
        uint256     _expirationDate)
        internal
        view
        returns(bytes32)
    {
        return keccak256(this,_requestData, _payeesPaymentAddress, _expirationDate);
    }

    /*
     * @dev Verifies that a hash signature is valid. 0x style
     * @param signer address of signer.
     * @param hash Signed Keccak-256 hash.
     * @param v ECDSA signature parameter v.
     * @param r ECDSA signature parameters r.
     * @param s ECDSA signature parameters s.
     * @return Validity of order signature.
     */
    function isValidSignature(
        address signer,
        bytes32 hash,
        uint8   v,
        bytes32 r,
        bytes32 s)
        public
        pure
        returns (bool)
    {
        return signer == ecrecover(
            keccak256("\x19Ethereum Signed Message:\n32", hash),
            v,
            r,
            s
        );
    }

    /*
     * @dev extract an address in a bytes
     * @param data bytes from where the address will be extract
     * @param offset position of the first byte of the address
     * @return address
     */
    function extractAddress(bytes _data, uint offset)
        internal
        pure
        returns (address m) 
    {
        require(offset >=0 && offset + 20 <= _data.length);
        assembly {
            m := and( mload(add(_data, add(20, offset))), 
                      0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        }
    }

    /*
     * @dev extract a bytes32 from a bytes
     * @param data bytes from where the bytes32 will be extract
     * @param offset position of the first byte of the bytes32
     * @return address
     */
    function extractBytes32(bytes _data, uint offset)
        public
        pure
        returns (bytes32 bs)
    {
        require(offset >=0 && offset + 32 <= _data.length);
        assembly {
            bs := mload(add(_data, add(32, offset)))
        }
    }

    /*
     * @dev modify 20 bytes in a bytes
     * @param data bytes to modify
     * @param offset position of the first byte to modify
     * @param b bytes20 to insert
     * @return address
     */
    function updateBytes20inBytes(bytes data, uint offset, bytes20 b)
        internal
        pure
    {
        require(offset >=0 && offset + 20 <= data.length);
        assembly {
            let m := mload(add(data, add(20, offset)))
            m := and(m, 0xFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000)
            m := or(m, div(b, 0x1000000000000000000000000))
            mstore(add(data, add(20, offset)), m)
        }
    }
}

Contract ABI
[{"constant":true,"inputs":[{"name":"_expectedAmount","type":"int256"}],"name":"collectEstimation","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rateFeesNumerator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"bytes32"},{"name":"_payeeAmounts","type":"uint256[]"},{"name":"_additionalAmounts","type":"uint256[]"}],"name":"paymentAction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"bytes32"},{"name":"_subtractAmounts","type":"uint256[]"}],"name":"subtractAction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_requestData","type":"bytes"},{"name":"_payeesPaymentAddress","type":"address[]"},{"name":"_expirationDate","type":"uint256"},{"name":"_signature","type":"bytes"}],"name":"checkRequestSignature","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_requestData","type":"bytes"},{"name":"_payeesPaymentAddress","type":"address[]"},{"name":"_payeeAmounts","type":"uint256[]"},{"name":"_additionals","type":"uint256[]"},{"name":"_expirationDate","type":"uint256"},{"name":"_signature","type":"bytes"}],"name":"broadcastSignedRequestAsPayerAction","outputs":[{"name":"requestId","type":"bytes32"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_requestBurnerContract","type":"address"}],"name":"setRequestBurnerContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_payeesIdAddress","type":"address[]"},{"name":"_payeesPaymentAddress","type":"address[]"},{"name":"_expectedAmounts","type":"int256[]"},{"name":"_payer","type":"address"},{"name":"_payerRefundAddress","type":"address"},{"name":"_data","type":"string"}],"name":"createRequestAsPayeeAction","outputs":[{"name":"requestId","type":"bytes32"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"requestCore","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rateFeesDenominator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"bytes32"}],"name":"cancelAction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"signer","type":"address"},{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"isValidSignature","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"bytes32"},{"name":"_additionalAmounts","type":"uint256[]"}],"name":"additionalAction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"erc20Token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"payerRefundAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"bytes32"}],"name":"acceptAction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_data","type":"bytes"},{"name":"offset","type":"uint256"}],"name":"extractBytes32","outputs":[{"name":"bs","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"name":"payeesPaymentAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_rateFeesNumerator","type":"uint256"},{"name":"_rateFeesDenominator","type":"uint256"}],"name":"setRateFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_payeesIdAddress","type":"address[]"},{"name":"_expectedAmounts","type":"int256[]"},{"name":"_payerRefundAddress","type":"address"},{"name":"_payeeAmounts","type":"uint256[]"},{"name":"_additionals","type":"uint256[]"},{"name":"_data","type":"string"}],"name":"createRequestAsPayerAction","outputs":[{"name":"requestId","type":"bytes32"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_newMaxFees","type":"uint256"}],"name":"setMaxCollectable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"requestBurnerContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxFees","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_requestId","type":"bytes32"},{"name":"_amountToRefund","type":"uint256"}],"name":"refundAction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_requestCoreAddress","type":"address"},{"name":"_requestBurnerAddress","type":"address"},{"name":"_erc20Token","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"rateFeesNumerator","type":"uint256"},{"indexed":false,"name":"rateFeesDenominator","type":"uint256"}],"name":"UpdateRateFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxFees","type":"uint256"}],"name":"UpdateMaxFees","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

Contract Creation Code
606060405260008060146101000a81548160ff021916908315150217905550341561002957600080fd5b60405160608061458b83398101604052808051906020019091908051906020019091908051906020019091905050828280336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505080600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050614419806101726000396000f300606060405260043610610175576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318954b3e1461017a578063263f6a42146101b157806327dd16e5146101da578063289b45fb146102295780633f4ba83a146102905780634b0a0d04146102a557806350faaeff146103a6578063524eb29c1461043e5780635c975abb14610477578063629873b2146104a45780636c4fbaa41461055d57806375c268f3146105b2578063781cc3d3146105db5780638163681e1461060257806383565cc7146106865780638456cb59146106ed5780638a13eea7146107025780638da5cb5b14610757578063a460b89c146107ac578063a9de504514610813578063b1e05e8a1461083a578063b2f35bdd146108bc578063c60116331461092c578063d5d067b014610958578063d7b8de0014610a06578063e40e845714610a29578063e83e34b114610a7e578063e9187ef414610aa7578063f2fde38b14610ad7575b600080fd5b341561018557600080fd5b61019b6004808035906020019091905050610b10565b6040518082815260200191505060405180910390f35b34156101bc57600080fd5b6101c4610b7c565b6040518082815260200191505060405180910390f35b34156101e557600080fd5b61022760048080356000191690602001909190803590602001908201803590602001919091929080359060200190820180359060200191909192905050610b82565b005b341561023457600080fd5b61028e60048080356000191690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610dfb565b005b341561029b57600080fd5b6102a3611318565b005b34156102b057600080fd5b61038c600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506113d6565b604051808215151515815260200191505060405180910390f35b6104206004808035906020019082018035906020019190919290803590602001908201803590602001919091929080359060200190820180359060200191909192908035906020019082018035906020019190919290803590602001909190803590602001908201803590602001919091929050506114d4565b60405180826000191660001916815260200191505060405180910390f35b341561044957600080fd5b610475600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611686565b005b341561048257600080fd5b61048a611725565b604051808215151515815260200191505060405180910390f35b61053f600480803590602001908201803590602001919091929080359060200190820180359060200191909192908035906020019082018035906020019190919290803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200191909192905050611738565b60405180826000191660001916815260200191505060405180910390f35b341561056857600080fd5b610570611a41565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156105bd57600080fd5b6105c5611a67565b6040518082815260200191505060405180910390f35b34156105e657600080fd5b610600600480803560001916906020019091905050611a6d565b005b341561060d57600080fd5b61066c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611faa565b604051808215151515815260200191505060405180910390f35b341561069157600080fd5b6106eb600480803560001916906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506120b1565b005b34156106f857600080fd5b6107006124c6565b005b341561070d57600080fd5b610715612586565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561076257600080fd5b61076a6125ac565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156107b757600080fd5b6107d16004808035600019169060200190919050506125d1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561081e57600080fd5b610838600480803560001916906020019091905050612604565b005b341561084557600080fd5b61089e600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919080359060200190919050506128a6565b60405180826000191660001916815260200191505060405180910390f35b34156108c757600080fd5b6108ea6004808035600019169060200190919080359060200190919050506128d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561093757600080fd5b610956600480803590602001909190803590602001909190505061291b565b005b6109e860048080359060200190820180359060200191909192908035906020019082018035906020019190919290803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200191909192908035906020019082018035906020019190919290803590602001908201803590602001919091929050506129cb565b60405180826000191660001916815260200191505060405180910390f35b3415610a1157600080fd5b610a276004808035906020019091905050612c3a565b005b3415610a3457600080fd5b610a3c612cd8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3415610a8957600080fd5b610a91612cfe565b6040518082815260200191505060405180910390f35b3415610ab257600080fd5b610ad5600480803560001916906020019091908035906020019091905050612d04565b005b3415610ae257600080fd5b610b0e600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612d2f565b005b6000806000831215610b255760009150610b76565b610b3a60015484612e8490919063ffffffff16565b90506000600254141515610b6057610b5d60025482612eb790919063ffffffff16565b90505b6003548110610b7157600354610b73565b805b91505b50919050565b60015481565b600060149054906101000a900460ff16151515610b9e57600080fd5b60006002811115610bab57fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d876000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515610c4c57600080fd5b6102c65a03f11515610c5d57600080fd5b505050604051805190506002811115610c7257fe5b148015610d655750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a12cad70866000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515610d1b57600080fd5b6102c65a03f11515610d2c57600080fd5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15610d7457610d7385612604565b5b600082829050141515610dbb57610dba858383808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050506120b1565b5b610df485858580806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050612ed2565b5050505050565b60008060149054906101000a900460ff16151515610e1857600080fd5b823373ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392fd1f0183600080604051602001526040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600019166000191681526020018260ff16815260200192505050602060405180830381600087803b1515610edc57600080fd5b6102c65a03f11515610eed57600080fd5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff16141515610f1957600080fd5b600280811115610f2557fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d866000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515610fc657600080fd5b6102c65a03f11515610fd757600080fd5b505050604051805190506002811115610fec57fe5b14151515610ff957600080fd5b6110cb6001600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663caef5dec876000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b151561109f57600080fd5b6102c65a03f115156110b057600080fd5b5050506040518051905060ff1661338a90919063ffffffff16565b60ff168351111515156110dd57600080fd5b600091505b82518260ff161015611312576000838360ff1681518110151561110157fe5b906020019060200201511415156112f457611135838360ff1681518110151561112657fe5b906020019060200201516133ae565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632ad8d87586856000604051602001526040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600019166000191681526020018260ff1660ff16815260200192505050602060405180830381600087803b15156111e457600080fd5b6102c65a03f115156111f557600080fd5b505050604051805190501215151561120c57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ce165894858461126f878760ff1681518110151561126057fe5b906020019060200201516133ae565b6000036040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018360ff1660ff1681526020018281526020019350505050600060405180830381600087803b15156112df57600080fd5b6102c65a03f115156112f057600080fd5b5050505b61130b60018360ff1661338a90919063ffffffff16565b91506110e2565b50505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561137357600080fd5b600060149054906101000a900460ff16151561138e57600080fd5b60008060146101000a81548160ff0219169083151502179055507f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a1565b60008060008060006113e98989896133ca565b93508560408151811015156113fa57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049250601b8360ff161061147b5782611493565b611492601b8460ff1661338a90919063ffffffff16565b5b92506114a08660006128a6565b91506114ad8660206128a6565b90506114c66114bd8a60006134b8565b85858585611faa565b945050505050949350505050565b60008060149054906101000a900460ff161515156114f157600080fd5b42841015151561150057600080fd5b61159f8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050508686868080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506113d6565b15156115aa57600080fd5b6116758c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050508a8a808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050508989808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050506134fe565b90509b9a5050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156116e157600080fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600060149054906101000a900460ff1681565b600080600080600060149054906101000a900460ff1615151561175a57600080fd5b8d8d6000818110151561176957fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156117ec57508773ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b801561180f575060008873ffffffffffffffffffffffffffffffffffffffff1614155b151561181a57600080fd5b6118b6888f8f808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050508c8c8080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505089898080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506138ec565b80945081955050506118c783610b10565b915034821480156118dd57506118dc82613bb7565b5b15156118e857600080fd5b600090505b8b8b90508160ff1610156119b2578b8b8260ff16818110151561190c57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166006600086600019166000191681526020019081526020016000208260ff166101008110151561195557fe5b0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506119ab60018260ff1661338a90919063ffffffff16565b90506118ed565b60008773ffffffffffffffffffffffffffffffffffffffff16141515611a2d578660076000866000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b8393505050509a9950505050505050505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b600060149054906101000a900460ff16151515611a8957600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a12cad70836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515611b4157600080fd5b6102c65a03f11515611b5257600080fd5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff16148015611c50575060006002811115611b8757fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515611c2857600080fd5b6102c65a03f11515611c3957600080fd5b505050604051805190506002811115611c4e57fe5b145b80611e2957503373ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392fd1f0183600080604051602001526040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600019166000191681526020018260ff16815260200192505050602060405180830381600087803b1515611d1957600080fd5b6102c65a03f11515611d2a57600080fd5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff16148015611e285750600280811115611d5e57fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515611dff57600080fd5b6102c65a03f11515611e1057600080fd5b505050604051805190506002811115611e2557fe5b14155b5b1515611e3457600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166307550f0a826000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515611ed557600080fd5b6102c65a03f11515611ee657600080fd5b505050604051805190501515611efb57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c4d252f5826040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050600060405180830381600087803b1515611f9357600080fd5b6102c65a03f11515611fa457600080fd5b50505050565b600060018560405180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040518091039020858585604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561206f57600080fd5b50506020604051035173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614905095945050505050565b60008060149054906101000a900460ff161515156120ce57600080fd5b823373ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a12cad70836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b151561218757600080fd5b6102c65a03f1151561219857600080fd5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff161415156121c457600080fd5b6002808111156121d057fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d866000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b151561227157600080fd5b6102c65a03f1151561228257600080fd5b50505060405180519050600281111561229757fe5b141515156122a457600080fd5b6123766001600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663caef5dec876000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b151561234a57600080fd5b6102c65a03f1151561235b57600080fd5b5050506040518051905060ff1661338a90919063ffffffff16565b60ff1683511115151561238857600080fd5b600091505b82518260ff1610156124c0576000838360ff168151811015156123ac57fe5b906020019060200201511415156124a257600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ce1658948584612420878760ff1681518110151561241157fe5b906020019060200201516133ae565b6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018360ff1660ff1681526020018281526020019350505050600060405180830381600087803b151561248d57600080fd5b6102c65a03f1151561249e57600080fd5b5050505b6124b960018360ff1661338a90919063ffffffff16565b915061238d565b50505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561252157600080fd5b600060149054906101000a900460ff1615151561253d57600080fd5b6001600060146101000a81548160ff0219169083151502179055507f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a1565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff1615151561262057600080fd5b803373ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a12cad70836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b15156126d957600080fd5b6102c65a03f115156126ea57600080fd5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff1614151561271657600080fd5b6000600281111561272357fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d846000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b15156127c457600080fd5b6102c65a03f115156127d557600080fd5b5050506040518051905060028111156127ea57fe5b1415156127f657600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e4725ba1836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050600060405180830381600087803b151561288e57600080fd5b6102c65a03f1151561289f57600080fd5b5050505050565b60008082101580156128bc575082516020830111155b15156128c757600080fd5b81602001830151905092915050565b600660205281600052604060002081610100811015156128f257fe5b016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561297657600080fd5b81600181905550806002819055507f74001f9764398216f36f3f1c1e3271c5a965a45dfa33bb132c699ed6e171ab1f600154600254604051808381526020018281526020019250505060405180910390a15050565b600080600060149054906101000a900460ff161515156129ea57600080fd5b8c8c600081811015156129f957fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015612a93575060008d8d60008181101515612a5d57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b1515612a9e57600080fd5b612b3a338e8e808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050508d8d8080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505087878080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506138ec565b809250819350505060008973ffffffffffffffffffffffffffffffffffffffff16141515612bbd578860076000846000191660001916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b612c278289898080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505088888080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505084613c17565b819150509b9a5050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612c9557600080fd5b806003819055507f6b1c63dd26ab451d994d7f5c0b5b6e9425a2da8206cb849a5c33e34a68b011686003546040518082815260200191505060405180910390a150565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b600060149054906101000a900460ff16151515612d2057600080fd5b612d2b823383613c44565b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612d8a57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612dc657600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008082840290506000841480612ea55750828482811515612ea257fe5b04145b1515612ead57fe5b8091505092915050565b6000808284811515612ec557fe5b0490508091505092915050565b600080600280811115612ee157fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d866000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515612f8257600080fd5b6102c65a03f11515612f9357600080fd5b505050604051805190506002811115612fa857fe5b14151515612fb557600080fd5b6130876001600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663caef5dec876000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b151561305b57600080fd5b6102c65a03f1151561306c57600080fd5b5050506040518051905060ff1661338a90919063ffffffff16565b60ff1683511115151561309957600080fd5b600091505b82518260ff161015613384576000838360ff168151811015156130bd57fe5b9060200190602002015114151561336657600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b073f52b8584613131878760ff1681518110151561312257fe5b906020019060200201516133ae565b6040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018360ff1660ff1681526020018281526020019350505050600060405180830381600087803b151561319e57600080fd5b6102c65a03f115156131af57600080fd5b50505060006006600086600019166000191681526020019081526020016000208360ff16610100811015156131e057fe5b0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156132ef57600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392fd1f0185846000604051602001526040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600019166000191681526020018260ff1660ff16815260200192505050602060405180830381600087803b15156132cd57600080fd5b6102c65a03f115156132de57600080fd5b505050604051805190509050613340565b6006600085600019166000191681526020019081526020016000208260ff166101008110151561331b57fe5b0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b6133653382858560ff1681518110151561335657fe5b906020019060200201516141f4565b5b61337d60018360ff1661338a90919063ffffffff16565b915061309e565b50505050565b60008082840190508360ff168160ff16101515156133a457fe5b8091505092915050565b600080829050600081121515156133c157fe5b80915050919050565b600030848484604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140184805190602001908083835b6020831015156134465780518252602082019150602081019050602083039250613421565b6001836020036101000a038019825116818451168082178552505050505050905001838051906020019060200280838360005b83811015613494578082015181840152602081019050613479565b50505050905001828152602001945050505050604051809103902090509392505050565b60008082101580156134ce575082516014830111155b15156134d957600080fd5b73ffffffffffffffffffffffffffffffffffffffff8260140184015116905092915050565b6000806000806000806000806135158c60296134b8565b96508673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561356a575060008773ffffffffffffffffffffffffffffffffffffffff1614155b151561357557600080fd5b8673ffffffffffffffffffffffffffffffffffffffff166135978d60006134b8565b73ffffffffffffffffffffffffffffffffffffffff161415156135b957600080fd5b8b60288151811015156135c857fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f01000000000000000000000000000000000000000000000000000000000000009004955060009450600093505b8560ff168460ff1610156136b9576136828c61367d603d61366f60348960ff16612e8490919063ffffffff16565b61432090919063ffffffff16565b6128a6565b60019004925061369b838661433e90919063ffffffff16565b94506000831315156136ac57600080fd5b8380600101945050613641565b6136c285610b10565b915034821480156136d857506136d782613bb7565b5b15156136e357600080fd5b6136fe8c6014336c010000000000000000000000000261437f565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1cda4688d6000604051602001526040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825283818151815260200191508051906020019080838360005b838110156137b1578082015181840152602081019050613796565b50505050905090810190601f1680156137de5780820380516001836020036101000a031916815260200191505b5092505050602060405180830381600087803b15156137fc57600080fd5b6102c65a03f1151561380d57600080fd5b505050604051805190509750600090505b8a518160ff1610156138ce578a8160ff1681518110151561383b57fe5b90602001906020020151600660008a600019166000191681526020019081526020016000208260ff166101008110151561387157fe5b0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506138c760018260ff1661338a90919063ffffffff16565b905061381e565b6138da888b8b88613c17565b87975050505050505050949350505050565b60008060008060149054906101000a900460ff1615151561390c57600080fd5b60009150600090505b84518160ff161015613998576000858260ff1681518110151561393457fe5b906020019060200201511215151561394b57600080fd5b613978858260ff1681518110151561395f57fe5b906020019060200201518361433e90919063ffffffff16565b915061399160018260ff1661338a90919063ffffffff16565b9050613915565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663431072903388888b896000604051602001526040518663ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001848103845288818151815260200191508051906020019060200280838360005b83811015613abe578082015181840152602081019050613aa3565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015613b00578082015181840152602081019050613ae5565b50505050905001848103825285818151815260200191508051906020019080838360005b83811015613b3f578082015181840152602081019050613b24565b50505050905090810190601f168015613b6c5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1515613b9057600080fd5b6102c65a03f11515613ba157600080fd5b5050506040518051905092505094509492505050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050509050919050565b613c2084612604565b613c2a84836120b1565b6000811315613c3e57613c3d8484612ed2565b5b50505050565b600080600080600280811115613c5657fe5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309648a9d896000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515613cf757600080fd5b6102c65a03f11515613d0857600080fd5b505050604051805190506002811115613d1d57fe5b14151515613d2a57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f6112d6888886000604051602001526040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600019166000191681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600087803b1515613dff57600080fd5b6102c65a03f11515613e1057600080fd5b505050604051805190509350613eee6001600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663caef5dec8a6000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1515613ec257600080fd5b6102c65a03f11515613ed357600080fd5b5050506040518051905060ff1661338a90919063ffffffff16565b925060008460010b1215613fe457600091505b8260ff168260ff16108015613f3857507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8460010b145b15613fe3578573ffffffffffffffffffffffffffffffffffffffff166006600089600019166000191681526020019081526020016000208360ff1661010081101515613f8057fe5b0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613fc5578160ff1693505b613fdc60018360ff1661338a90919063ffffffff16565b9150613f01565b5b60008460010b12151515613ff757600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b073f52b8886614040896133ae565b6000036040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600019166000191681526020018360ff1660ff1681526020018281526020019350505050600060405180830381600087803b15156140b057600080fd5b6102c65a03f115156140c157600080fd5b50505060076000886000191660001916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff1614156141e057600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a12cad70886000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b15156141c257600080fd5b6102c65a03f115156141d357600080fd5b5050506040518051905090505b6141eb8682876141f4565b50505050505050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd8484846000604051602001526040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15156142f557600080fd5b6102c65a03f1151561430657600080fd5b50505060405180519050151561431b57600080fd5b505050565b600080828401905083811015151561433457fe5b8091505092915050565b6000808284019050600083121580156143575750838112155b8061436d575060008312801561436c57508381125b5b151561437557fe5b8091505092915050565b60008210158015614394575082516014830111155b151561439f57600080fd5b816014018301517fffffffffffffffffffffffff0000000000000000000000000000000000000000811690506c010000000000000000000000008204811790508083601401850152505050505600a165627a7a72305820ec7372fec84f128d2f7e797f93f19bfac6bef3eb77daf5bf103ed2d9b2e175be0029000000000000000000000000db600fda54568a35b78565b5257125bebc51eb27000000000000000000000000fcb4393e7faef06fab01c00d67c1895545aff3b80000000000000000000000008f8221afbb33998d8584a2b05749ba73c37a938a


   Swarm Source:
bzzr://ec7372fec84f128d2f7e797f93f19bfac6bef3eb77daf5bf103ed2d9b2e175be
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.