// Vulnerability label: NC1
{{
  "language": "Solidity",
  "sources": {
    "contracts/5/EIP1167/CloneFactory.sol": {
      "content": "pragma solidity 0.5.16;\n\n/*\nThe MIT License (MIT)\n\nCopyright (c) 2018 Murray Software, LLC.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n//solhint-disable max-line-length\n//solhint-disable no-inline-assembly\n\ncontract CloneFactory {\n\n  function createClone(address target) internal returns (address result) {\n    bytes20 targetBytes = bytes20(target);\n    assembly {\n      let clone := mload(0x40)\n      mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n      mstore(add(clone, 0x14), targetBytes)\n      mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n      result := create(0, clone, 0x37)\n    }\n  }\n\n  function isClone(address target, address query) internal view returns (bool result) {\n    bytes20 targetBytes = bytes20(target);\n    assembly {\n      let clone := mload(0x40)\n      mstore(clone, 0x363d3d373d3d3d363d7300000000000000000000000000000000000000000000)\n      mstore(add(clone, 0xa), targetBytes)\n      mstore(add(clone, 0x1e), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n\n      let other := add(clone, 0x40)\n      extcodecopy(query, other, 0, 0x2d)\n      result := and(\n        eq(mload(clone), mload(other)),\n        eq(mload(add(clone, 0xd)), mload(add(other, 0xd)))\n      )\n    }\n  }\n}\n"
    },
    "contracts/5/Fantastic12.sol": {
      "content": "pragma solidity 0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./standard_bounties/StandardBountiesWrapper.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract Fantastic12 {\n  using SafeMath for uint256;\n  using SafeERC20 for IERC20;\n  using StandardBountiesWrapper for address;\n\n  // Constants\n  uint8   public constant MAX_MEMBERS = 12;\n  string  public constant VERSION = \"0.1.4\";\n  uint256 internal constant PRECISION = 10 ** 18;\n\n  // Instance variables\n  mapping(address => bool) public isMember;\n  mapping(address => mapping(uint256 => bool)) public hasUsedSalt; // Stores whether a salt has been used for a member\n  uint8 public memberCount;\n  IERC20 public DAI;\n  address payable[] public issuersOrFulfillers;\n  address[] public approvers;\n  uint256 public withdrawLimit;\n  uint256 public withdrawnToday;\n  uint256 public lastWithdrawTimestamp;\n  uint256 public consensusThresholdPercentage; // at least (consensusThresholdPercentage * memberCount / PRECISION) approvers are needed to execute an action\n  bool public initialized;\n\n  // Modifiers\n  modifier onlyMember {\n    require(isMember[msg.sender], \"Not member\");\n    _;\n  }\n\n  modifier withConsensus(\n    bytes4           _funcSelector,\n    bytes     memory _funcParams,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  ) {\n    require(\n      _consensusReached(\n        consensusThreshold(),\n        _funcSelector,\n        _funcParams,\n        _members,\n        _signatures,\n        _salts\n      ), \"No consensus\");\n    _;\n  }\n\n  modifier withUnanimity(\n    bytes4           _funcSelector,\n    bytes     memory _funcParams,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  ) {\n    require(\n      _consensusReached(\n        memberCount,\n        _funcSelector,\n        _funcParams,\n        _members,\n        _signatures,\n        _salts\n      ), \"No unanimity\");\n    _;\n  }\n\n  // Events\n  event Shout(string message);\n  event Declare(string message);\n  event AddMember(address newMember, uint256 tribute);\n  event RageQuit(address quitter);\n  event PostBounty(uint256 bountyID, uint256 reward);\n  event AddBountyReward(uint256 bountyID, uint256 reward);\n  event RefundBountyReward(uint256 bountyID, uint256 refundAmount);\n  event ChangeBountyData(uint256 bountyID);\n  event ChangeBountyDeadline(uint256 bountyID);\n  event AcceptBountySubmission(uint256 bountyID, uint256 fulfillmentID);\n  event PerformBountyAction(uint256 bountyID);\n  event FulfillBounty(uint256 bountyID);\n  event UpdateBountyFulfillment(uint256 bountyID, uint256 fulfillmentID);\n\n  // Initializer\n  function init(\n    address _summoner,\n    address _DAI_ADDR,\n    uint256 _withdrawLimit,\n    uint256 _consensusThresholdPercentage\n  ) public {\n    require(! initialized, \"Initialized\");\n    require(_consensusThresholdPercentage <= PRECISION, \"Consensus threshold > 1\");\n    initialized = true;\n    memberCount = 1;\n    DAI = IERC20(_DAI_ADDR);\n    issuersOrFulfillers = new address payable[](1);\n    issuersOrFulfillers[0] = address(this);\n    approvers = new address[](1);\n    approvers[0] = address(this);\n    withdrawLimit = _withdrawLimit;\n    consensusThresholdPercentage = _consensusThresholdPercentage;\n\n    // Add `_summoner` as the first member\n    isMember[_summoner] = true;\n  }\n\n  // Functions\n\n  /**\n    Censorship-resistant messaging\n   */\n  function shout(string memory _message) public onlyMember {\n    emit Shout(_message);\n  }\n\n  function declare(\n    string memory _message,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.declare.selector,\n      abi.encode(_message),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    emit Declare(_message);\n  }\n\n  /**\n    Member management\n   */\n\n  function addMembers(\n    address[] memory _newMembers,\n    uint256[] memory _tributes,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.addMembers.selector,\n      abi.encode(_newMembers, _tributes),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    require(_newMembers.length == _tributes.length, \"_newMembers not same length as _tributes\");\n    for (uint256 i = 0; i < _newMembers.length; i = i.add(1)) {\n      _addMember(_newMembers[i], _tributes[i]);\n    }\n  }\n\n  function _addMember(\n    address _newMember,\n    uint256 _tribute\n  )\n    internal\n  {\n    require(_newMember != address(0), \"Member cannot be zero address\");\n    require(!isMember[_newMember], \"Member cannot be added twice\");\n    require(memberCount < MAX_MEMBERS, \"Max member count reached\");\n\n    // Receive tribute from `_newMember`\n    require(DAI.transferFrom(_newMember, address(this), _tribute), \"Tribute transfer failed\");\n\n    // Add `_newMember` to squad\n    isMember[_newMember] = true;\n    memberCount += 1;\n\n    emit AddMember(_newMember, _tribute);\n  }\n\n  function rageQuit() public onlyMember {\n    // Give `msg.sender` their portion of the squad funds\n    uint256 withdrawAmount;\n    withdrawAmount = DAI.balanceOf(address(this)).div(memberCount);\n    DAI.safeTransfer(msg.sender, withdrawAmount);\n\n    // Remove `msg.sender` from squad\n    isMember[msg.sender] = false;\n    memberCount -= 1;\n    emit RageQuit(msg.sender);\n  }\n\n  function rageQuitWithTokens(address[] memory _tokens) public onlyMember {\n    // Give `msg.sender` their portion of the squad funds\n    uint256 withdrawAmount;\n    for (uint256 i = 0; i < _tokens.length; i = i.add(1)) {\n      if (_tokens[i] == address(0)) {\n        withdrawAmount = address(this).balance.div(memberCount);\n        msg.sender.transfer(withdrawAmount);\n      } else {\n        IERC20 token = IERC20(_tokens[i]);\n        withdrawAmount = token.balanceOf(address(this)).div(memberCount);\n        token.safeTransfer(msg.sender, withdrawAmount);\n      }\n    }\n\n    // Remove `msg.sender` from squad\n    isMember[msg.sender] = false;\n    memberCount -= 1;\n    emit RageQuit(msg.sender);\n  }\n\n  /**\n    Fund management\n   */\n\n  function transferDAI(\n    address[] memory _dests,\n    uint256[] memory _amounts,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.transferDAI.selector,\n      abi.encode(_dests, _amounts),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    require(_dests.length == _amounts.length, \"_dests not same length as _amounts\");\n    for (uint256 i = 0; i < _dests.length; i = i.add(1)) {\n      _transferDAI(_dests[i], _amounts[i]);\n    }\n  }\n\n  function transferTokens(\n    address payable[] memory _dests,\n    uint256[] memory _amounts,\n    address[] memory _tokens,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.transferTokens.selector,\n      abi.encode(_dests, _amounts, _tokens),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    require(_dests.length == _amounts.length && _dests.length == _tokens.length, \"_dests, _amounts, _tokens not of same length\");\n    for (uint256 i = 0; i < _dests.length; i = i.add(1)) {\n      if (_tokens[i] == address(0)) {\n        _dests[i].transfer(_amounts[i]);\n      } else if (_tokens[i] == address(DAI)) {\n        _transferDAI(_dests[i], _amounts[i]);\n      } else {\n        IERC20 token = IERC20(_tokens[i]);\n        token.safeTransfer(_dests[i], _amounts[i]);\n      }\n    }\n  }\n  \n  function setWithdrawLimit(\n    uint256 _newLimit,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withUnanimity(\n      this.setWithdrawLimit.selector,\n      abi.encode(_newLimit),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    withdrawLimit = _newLimit;\n  }\n\n  function setConsensusThreshold(\n    uint256 _newThresholdPercentage,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withUnanimity(\n      this.setConsensusThreshold.selector,\n      abi.encode(_newThresholdPercentage),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    consensusThresholdPercentage = _newThresholdPercentage;\n  }\n\n  /**\n    Posting bounties\n   */\n\n  function postBounty(\n    string memory _dataIPFSHash,\n    uint256 _deadline,\n    uint256 _reward,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.postBounty.selector,\n      abi.encode(_dataIPFSHash, _deadline, _reward, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n    returns (uint256 _bountyID)\n  {\n    return _postBounty(_dataIPFSHash, _deadline, _reward, _standardBounties, _standardBountiesVersion);\n  }\n\n  function _postBounty(\n    string memory _dataIPFSHash,\n    uint256 _deadline,\n    uint256 _reward,\n    address _standardBounties,\n    uint256 _standardBountiesVersion\n  )\n    internal\n    returns (uint256 _bountyID)\n  {\n    require(_reward > 0, \"Reward can't be 0\");\n\n    // Approve DAI reward to bounties contract\n    _approveDAI(_standardBounties, _reward);\n\n    _bountyID = _standardBounties.issueAndContribute(\n      _standardBountiesVersion,\n      address(this),\n      issuersOrFulfillers,\n      approvers,\n      _dataIPFSHash,\n      _deadline,\n      address(DAI),\n      _reward\n    );\n\n    emit PostBounty(_bountyID, _reward);\n  }\n\n  function addBountyReward(\n    uint256 _bountyID,\n    uint256 _reward,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.addBountyReward.selector,\n      abi.encode(_bountyID, _reward, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    // Approve DAI reward to bounties contract\n    _approveDAI(_standardBounties, _reward);\n\n    _standardBounties.contribute(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      _reward\n    );\n\n    emit AddBountyReward(_bountyID, _reward);\n  }\n\n  function refundBountyReward(\n    uint256 _bountyID,\n    uint256[] memory _contributionIDs,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.refundBountyReward.selector,\n      abi.encode(_bountyID, _contributionIDs, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    uint256 beforeBalance = DAI.balanceOf(address(this));\n    _standardBounties.refundMyContributions(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      _contributionIDs\n    );\n\n    emit RefundBountyReward(_bountyID, DAI.balanceOf(address(this)).sub(beforeBalance));\n  }\n\n  function changeBountyData(\n    uint256 _bountyID,\n    string memory _dataIPFSHash,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.changeBountyData.selector,\n      abi.encode(_bountyID, _dataIPFSHash, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    _standardBounties.changeData(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      _dataIPFSHash\n    );\n    emit ChangeBountyData(_bountyID);\n  }\n\n  function changeBountyDeadline(\n    uint256 _bountyID,\n    uint256 _deadline,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.changeBountyDeadline.selector,\n      abi.encode(_bountyID, _deadline, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    _standardBounties.changeDeadline(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      _deadline\n    );\n    emit ChangeBountyDeadline(_bountyID);\n  }\n\n  function acceptBountySubmission(\n    uint256 _bountyID,\n    uint256 _fulfillmentID,\n    uint256[] memory _tokenAmounts,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.acceptBountySubmission.selector,\n      abi.encode(_bountyID, _fulfillmentID, _tokenAmounts, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    _standardBounties.acceptFulfillment(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      _fulfillmentID,\n      _tokenAmounts\n    );\n    emit AcceptBountySubmission(_bountyID, _fulfillmentID);\n  }\n\n  /**\n    Working on bounties\n   */\n\n  function performBountyAction(\n    uint256 _bountyID,\n    string memory _dataIPFSHash,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.performBountyAction.selector,\n      abi.encode(_bountyID, _dataIPFSHash, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    _standardBounties.performAction(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      _dataIPFSHash\n    );\n    emit PerformBountyAction(_bountyID);\n  }\n\n  function fulfillBounty(\n    uint256 _bountyID,\n    string memory _dataIPFSHash,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.fulfillBounty.selector,\n      abi.encode(_bountyID, _dataIPFSHash, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    _standardBounties.fulfillBounty(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      issuersOrFulfillers,\n      _dataIPFSHash\n    );\n    emit FulfillBounty(_bountyID);\n  }\n\n  function updateBountyFulfillment(\n    uint256 _bountyID,\n    uint256 _fulfillmentID,\n    string memory _dataIPFSHash,\n    address _standardBounties,\n    uint256 _standardBountiesVersion,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  )\n    public\n    withConsensus(\n      this.updateBountyFulfillment.selector,\n      abi.encode(_bountyID, _fulfillmentID, _dataIPFSHash, _standardBounties, _standardBountiesVersion),\n      _members,\n      _signatures,\n      _salts\n    )\n  {\n    _updateBountyFulfillment(_bountyID, _fulfillmentID, _dataIPFSHash, _standardBounties, _standardBountiesVersion);\n  }\n\n  function _updateBountyFulfillment(\n    uint256 _bountyID,\n    uint256 _fulfillmentID,\n    string memory _dataIPFSHash,\n    address _standardBounties,\n    uint256 _standardBountiesVersion\n  )\n    internal\n  {\n    _standardBounties.updateFulfillment(\n      _standardBountiesVersion,\n      address(this),\n      _bountyID,\n      _fulfillmentID,\n      issuersOrFulfillers,\n      _dataIPFSHash\n    );\n    emit UpdateBountyFulfillment(_bountyID, _fulfillmentID);\n  }\n\n  /**\n    Consensus\n   */\n\n  function naiveMessageHash(\n    bytes4       _funcSelector,\n    bytes memory _funcParams,\n    uint256      _salt\n  ) public view returns (bytes32) {\n    // \"|END|\" is used to separate _funcParams from the rest, to prevent maliciously ambiguous signatures\n    return keccak256(abi.encodeWithSelector(_funcSelector, _funcParams, \"|END|\", _salt, address(this)));\n  }\n\n  function consensusThreshold() public view returns (uint8) {\n    uint8 blockingThresholdMemberCount = uint8(PRECISION.sub(consensusThresholdPercentage).mul(memberCount).div(PRECISION));\n    return memberCount - blockingThresholdMemberCount;\n  }\n\n  function _consensusReached(\n    uint256          _threshold,\n    bytes4           _funcSelector,\n    bytes     memory _funcParams,\n    address[] memory _members,\n    bytes[]   memory _signatures,\n    uint256[] memory _salts\n  ) internal returns (bool) {\n    // Check if the number of signatures exceed the consensus threshold\n    if (_members.length != _signatures.length || _members.length < _threshold) {\n      return false;\n    }\n    // Check if each signature is valid and signed by a member\n    for (uint256 i = 0; i < _members.length; i = i.add(1)) {\n      address member = _members[i];\n      uint256 salt = _salts[i];\n      if (!isMember[member] || hasUsedSalt[member][salt]) {\n        // Invalid member or salt already used\n        return false;\n      }\n\n      bytes32 msgHash = ECDSA.toEthSignedMessageHash(naiveMessageHash(_funcSelector, _funcParams, salt));\n      address recoveredAddress = ECDSA.recover(msgHash, _signatures[i]);\n      if (recoveredAddress != member) {\n        // Invalid signature\n        return false;\n      }\n\n      // Signature valid, record use of salt\n      hasUsedSalt[member][salt] = true;\n    }\n\n    return true;\n  }\n\n  function _timestampToDayID(uint256 _timestamp) internal pure returns (uint256) {\n    return _timestamp.sub(_timestamp % 86400).div(86400);\n  }\n\n  // limits how much could be withdrawn each day, should be called before transfer() or approve()\n  function _applyWithdrawLimit(uint256 _amount) internal {\n    // check if the limit will be exceeded\n    if (_timestampToDayID(now).sub(_timestampToDayID(lastWithdrawTimestamp)) >= 1) {\n      // new day, don't care about existing limit\n      withdrawnToday = 0;\n    }\n    uint256 newWithdrawnToday = withdrawnToday.add(_amount);\n    require(newWithdrawnToday <= withdrawLimit, \"Withdraw limit exceeded\");\n    withdrawnToday = newWithdrawnToday;\n    lastWithdrawTimestamp = now;\n  }\n\n  function _transferDAI(address _to, uint256 _amount) internal {\n    _applyWithdrawLimit(_amount);\n    require(DAI.transfer(_to, _amount), \"Failed DAI transfer\");\n  }\n\n  function _approveDAI(address _to, uint256 _amount) internal {\n    _applyWithdrawLimit(_amount);\n    require(DAI.approve(_to, 0), \"Failed to clear DAI approval\");\n    require(DAI.approve(_to, _amount), \"Failed to approve DAI\");\n  }\n\n  function() external payable {}\n}"
    },
    "@openzeppelin/contracts/cryptography/ECDSA.sol": {
      "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * (.note) This call _does not revert_ if the signature is invalid, or\n     * if the signer is otherwise unable to be retrieved. In those scenarios,\n     * the zero address is returned.\n     *\n     * (.warning) `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise)\n     * be too long), and then calling `toEthSignedMessageHash` on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        // Check the signature length\n        if (signature.length != 65) {\n            return (address(0));\n        }\n\n        // Divide the signature in r, s and v variables\n        bytes32 r;\n        bytes32 s;\n        uint8 v;\n\n        // ecrecover takes the signature parameters, and the only way to get them\n        // currently is to use assembly.\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            r := mload(add(signature, 0x20))\n            s := mload(add(signature, 0x40))\n            v := byte(0, mload(add(signature, 0x60)))\n        }\n\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return address(0);\n        }\n\n        if (v != 27 && v != 28) {\n            return address(0);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        return ecrecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * replicates the behavior of the\n     * [`eth_sign`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign)\n     * JSON-RPC method.\n     *\n     * See `recover`.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\n * the optional functions; to access them see `ERC20Detailed`.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a `Transfer` event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through `transferFrom`. This is\n     * zero by default.\n     *\n     * This value changes when `approve` or `transferFrom` are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * > Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an `Approval` event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a `Transfer` event.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to `approve`. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
    },
    "contracts/5/standard_bounties/StandardBountiesWrapper.sol": {
      "content": "pragma solidity 0.5.16;\n\nimport \"./v1/IStandardBountiesV1.sol\";\nimport \"./v2/StandardBounties.sol\";\n\nlibrary StandardBountiesWrapper {\n  function issueAndContribute(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address payable _sender,\n    address payable[] memory _issuers,\n    address[] memory _approvers,\n    string memory _data,\n    uint _deadline,\n    address _token,\n    uint _depositAmount)\n    internal\n    returns(uint)\n  {\n    if (_standardBountiesVersion == 1) {\n      IStandardBountiesV1 BOUNTIES = IStandardBountiesV1(_standardBounties);\n      return BOUNTIES.issueAndActivateBounty(\n        _sender,\n        _deadline,\n        _data,\n        _depositAmount,\n        _sender,\n        true,\n        _token,\n        _depositAmount\n      );\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      return BOUNTIES.issueAndContribute(\n        _sender,\n        _issuers,\n        _approvers,\n        _data,\n        _deadline,\n        _token,\n        20, // ERC20\n        _depositAmount\n      );\n    }\n  }\n\n  function contribute(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address payable _sender,\n    uint _bountyId,\n    uint _amount)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      IStandardBountiesV1 BOUNTIES = IStandardBountiesV1(_standardBounties);\n      (,,uint fulfillmentAmount,,,) = BOUNTIES.getBounty(_bountyId);\n      BOUNTIES.increasePayout(\n        _bountyId,\n        add(fulfillmentAmount, _amount),\n        _amount\n      );\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.contribute(\n        _sender,\n        _bountyId,\n        _amount\n      );\n    }\n  }\n\n  function refundMyContributions(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address _sender,\n    uint _bountyId,\n    uint[] memory _contributionIds)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      IStandardBountiesV1 BOUNTIES = IStandardBountiesV1(_standardBounties);\n      BOUNTIES.killBounty(\n        _bountyId\n      );\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.refundMyContributions(\n        _sender,\n        _bountyId,\n        _contributionIds\n      );\n    }\n  }\n\n  function changeData(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address _sender,\n    uint _bountyId,\n    string memory _data)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      revert(\"Can't change data of V1 bounty\");\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.changeData(\n        _sender,\n        _bountyId,\n        0,\n        _data\n      );\n    }\n  }\n\n  function changeDeadline(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address _sender,\n    uint _bountyId,\n    uint _deadline)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      IStandardBountiesV1 BOUNTIES = IStandardBountiesV1(_standardBounties);\n      BOUNTIES.extendDeadline(\n        _bountyId,\n        _deadline\n      );\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.changeDeadline(\n        _sender,\n        _bountyId,\n        0,\n        _deadline\n      );\n    }\n  }\n\n  function acceptFulfillment(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address _sender,\n    uint _bountyId,\n    uint _fulfillmentId,\n    uint[] memory _tokenAmounts)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      IStandardBountiesV1 BOUNTIES = IStandardBountiesV1(_standardBounties);\n      BOUNTIES.acceptFulfillment(\n        _bountyId,\n        _fulfillmentId\n      );\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.acceptFulfillment(\n        _sender,\n        _bountyId,\n        _fulfillmentId,\n        0,\n        _tokenAmounts\n      );\n    }\n  }\n\n  function performAction(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address _sender,\n    uint _bountyId,\n    string memory _data)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      revert(\"Not supported by V1\");\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.performAction(\n        _sender,\n        _bountyId,\n        _data\n      );\n    }\n  }\n\n  function fulfillBounty(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address _sender,\n    uint _bountyId,\n    address payable[] memory  _fulfillers,\n    string memory _data)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      IStandardBountiesV1 BOUNTIES = IStandardBountiesV1(_standardBounties);\n      BOUNTIES.fulfillBounty(\n        _bountyId,\n        _data\n      );\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.fulfillBounty(\n        _sender,\n        _bountyId,\n        _fulfillers,\n        _data\n      );\n    }\n  }\n\n  function updateFulfillment(\n    address _standardBounties,\n    uint _standardBountiesVersion,\n    address _sender,\n    uint _bountyId,\n    uint _fulfillmentId,\n    address payable[] memory _fulfillers,\n    string memory _data)\n    internal\n  {\n    if (_standardBountiesVersion == 1) {\n      IStandardBountiesV1 BOUNTIES = IStandardBountiesV1(_standardBounties);\n      BOUNTIES.updateFulfillment(\n        _bountyId,\n        _fulfillmentId,\n        _data\n      );\n    } else if (_standardBountiesVersion == 2) {\n      StandardBounties BOUNTIES = StandardBounties(_standardBounties);\n      BOUNTIES.updateFulfillment(\n        _sender,\n        _bountyId,\n        _fulfillmentId,\n        _fulfillers,\n        _data\n      );\n    }\n  }\n\n  function add(uint256 a, uint256 b) internal pure returns (uint256) {\n    uint256 c = a + b;\n    require(c >= a, \"SafeMath: addition overflow\");\n\n    return c;\n  }\n}"
    },
    "contracts/5/standard_bounties/v1/IStandardBountiesV1.sol": {
      "content": "pragma solidity 0.5.16;\n\ninterface IStandardBountiesV1 {\n\n  /*\n   * Events\n   */\n  event BountyIssued(uint bountyId);\n  event BountyActivated(uint bountyId, address issuer);\n  event BountyFulfilled(uint bountyId, address indexed fulfiller, uint256 indexed _fulfillmentId);\n  event FulfillmentUpdated(uint _bountyId, uint _fulfillmentId);\n  event FulfillmentAccepted(uint bountyId, address indexed fulfiller, uint256 indexed _fulfillmentId);\n  event BountyKilled(uint bountyId, address indexed issuer);\n  event ContributionAdded(uint bountyId, address indexed contributor, uint256 value);\n  event DeadlineExtended(uint bountyId, uint newDeadline);\n  event BountyChanged(uint bountyId);\n  event IssuerTransferred(uint _bountyId, address indexed _newIssuer);\n  event PayoutIncreased(uint _bountyId, uint _newFulfillmentAmount);\n\n  /*\n   * Public functions\n   */\n\n  /// @dev issueBounty(): instantiates a new draft bounty\n  /// @param _issuer the address of the intended issuer of the bounty\n  /// @param _deadline the unix timestamp after which fulfillments will no longer be accepted\n  /// @param _data the requirements of the bounty\n  /// @param _fulfillmentAmount the amount of wei to be paid out for each successful fulfillment\n  /// @param _arbiter the address of the arbiter who can mediate claims\n  /// @param _paysTokens whether the bounty pays in tokens or in ETH\n  /// @param _tokenContract the address of the contract if _paysTokens is true\n  function issueBounty(\n    address _issuer,\n    uint _deadline,\n    string calldata _data,\n    uint256 _fulfillmentAmount,\n    address _arbiter,\n    bool _paysTokens,\n    address _tokenContract\n  )\n      external\n      returns (uint);\n\n  /// @dev issueAndActivateBounty(): instantiates a new draft bounty\n  /// @param _issuer the address of the intended issuer of the bounty\n  /// @param _deadline the unix timestamp after which fulfillments will no longer be accepted\n  /// @param _data the requirements of the bounty\n  /// @param _fulfillmentAmount the amount of wei to be paid out for each successful fulfillment\n  /// @param _arbiter the address of the arbiter who can mediate claims\n  /// @param _paysTokens whether the bounty pays in tokens or in ETH\n  /// @param _tokenContract the address of the contract if _paysTokens is true\n  /// @param _value the total number of tokens being deposited upon activation\n  function issueAndActivateBounty(\n    address _issuer,\n    uint _deadline,\n    string calldata _data,\n    uint256 _fulfillmentAmount,\n    address _arbiter,\n    bool _paysTokens,\n    address _tokenContract,\n    uint256 _value\n  )\n      external\n      payable\n      returns (uint);\n\n  /// @dev contribute(): a function allowing anyone to contribute tokens to a\n  /// bounty, as long as it is still before its deadline. Shouldn't keep\n  /// them by accident (hence 'value').\n  /// @param _bountyId the index of the bounty\n  /// @param _value the amount being contributed in ether to prevent accidental deposits\n  /// @notice Please note you funds will be at the mercy of the issuer\n  ///  and can be drained at any moment. Be careful!\n  function contribute (uint _bountyId, uint _value)\n      external\n      payable;\n\n  /// @notice Send funds to activate the bug bounty\n  /// @dev activateBounty(): activate a bounty so it may pay out\n  /// @param _bountyId the index of the bounty\n  /// @param _value the amount being contributed in ether to prevent\n  /// accidental deposits\n  function activateBounty(uint _bountyId, uint _value)\n      external\n      payable;\n\n  /// @dev fulfillBounty(): submit a fulfillment for the given bounty\n  /// @param _bountyId the index of the bounty\n  /// @param _data the data artifacts representing the fulfillment of the bounty\n  function fulfillBounty(uint _bountyId, string calldata _data)\n      external;\n\n  /// @dev updateFulfillment(): Submit updated data for a given fulfillment\n  /// @param _bountyId the index of the bounty\n  /// @param _fulfillmentId the index of the fulfillment\n  /// @param _data the new data being submitted\n  function updateFulfillment(uint _bountyId, uint _fulfillmentId, string calldata _data)\n      external;\n\n  /// @dev acceptFulfillment(): accept a given fulfillment\n  /// @param _bountyId the index of the bounty\n  /// @param _fulfillmentId the index of the fulfillment being accepted\n  function acceptFulfillment(uint _bountyId, uint _fulfillmentId)\n      external;\n\n  /// @dev killBounty(): drains the contract of it's remaining\n  /// funds, and moves the bounty into stage 3 (dead) since it was\n  /// either killed in draft stage, or never accepted any fulfillments\n  /// @param _bountyId the index of the bounty\n  function killBounty(uint _bountyId)\n      external;\n\n  /// @dev extendDeadline(): allows the issuer to add more time to the\n  /// bounty, allowing it to continue accepting fulfillments\n  /// @param _bountyId the index of the bounty\n  /// @param _newDeadline the new deadline in timestamp format\n  function extendDeadline(uint _bountyId, uint _newDeadline)\n      external;\n\n  /// @dev transferIssuer(): allows the issuer to transfer ownership of the\n  /// bounty to some new address\n  /// @param _bountyId the index of the bounty\n  /// @param _newIssuer the address of the new issuer\n  function transferIssuer(uint _bountyId, address _newIssuer)\n      external;\n\n\n  /// @dev changeBountyDeadline(): allows the issuer to change a bounty's deadline\n  /// @param _bountyId the index of the bounty\n  /// @param _newDeadline the new deadline for the bounty\n  function changeBountyDeadline(uint _bountyId, uint _newDeadline)\n      external;\n\n  /// @dev changeData(): allows the issuer to change a bounty's data\n  /// @param _bountyId the index of the bounty\n  /// @param _newData the new requirements of the bounty\n  function changeBountyData(uint _bountyId, string calldata _newData)\n      external;\n\n  /// @dev changeBountyfulfillmentAmount(): allows the issuer to change a bounty's fulfillment amount\n  /// @param _bountyId the index of the bounty\n  /// @param _newFulfillmentAmount the new fulfillment amount\n  function changeBountyFulfillmentAmount(uint _bountyId, uint _newFulfillmentAmount)\n      external;\n\n  /// @dev changeBountyArbiter(): allows the issuer to change a bounty's arbiter\n  /// @param _bountyId the index of the bounty\n  /// @param _newArbiter the new address of the arbiter\n  function changeBountyArbiter(uint _bountyId, address _newArbiter)\n      external;\n\n  /// @dev increasePayout(): allows the issuer to increase a given fulfillment\n  /// amount in the active stage\n  /// @param _bountyId the index of the bounty\n  /// @param _newFulfillmentAmount the new fulfillment amount\n  /// @param _value the value of the additional deposit being added\n  function increasePayout(uint _bountyId, uint _newFulfillmentAmount, uint _value)\n      external\n      payable;\n\n  /// @dev getFulfillment(): Returns the fulfillment at a given index\n  /// @param _bountyId the index of the bounty\n  /// @param _fulfillmentId the index of the fulfillment to return\n  /// @return Returns a tuple for the fulfillment\n  function getFulfillment(uint _bountyId, uint _fulfillmentId)\n      external\n      returns (bool, address, string memory);\n\n  /// @dev getBounty(): Returns the details of the bounty\n  /// @param _bountyId the index of the bounty\n  /// @return Returns a tuple for the bounty\n  function getBounty(uint _bountyId)\n      external\n      returns (address, uint, uint, bool, uint, uint);\n\n  /// @dev getBountyArbiter(): Returns the arbiter of the bounty\n  /// @param _bountyId the index of the bounty\n  /// @return Returns an address for the arbiter of the bounty\n  function getBountyArbiter(uint _bountyId)\n      external\n      returns (address);\n\n  /// @dev getBountyData(): Returns the data of the bounty\n  /// @param _bountyId the index of the bounty\n  /// @return Returns a string calldata for the bounty data\n  function getBountyData(uint _bountyId)\n      external\n      returns (string memory);\n\n  /// @dev getBountyToken(): Returns the token contract of the bounty\n  /// @param _bountyId the index of the bounty\n  /// @return Returns an address for the token that the bounty uses\n  function getBountyToken(uint _bountyId)\n      external\n      returns (address);\n\n  /// @dev getNumBounties() returns the number of bounties in the registry\n  /// @return Returns the number of bounties\n  function getNumBounties()\n      external\n      returns (uint);\n\n  /// @dev getNumFulfillments() returns the number of fulfillments for a given milestone\n  /// @param _bountyId the index of the bounty\n  /// @return Returns the number of fulfillments\n  function getNumFulfillments(uint _bountyId)\n      external\n      returns (uint);\n}"
    },
    "contracts/5/standard_bounties/v2/StandardBounties.sol": {
      "content": "pragma solidity 0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"./inherited/ERC20Token.sol\";\nimport \"./inherited/ERC721Basic.sol\";\n\n\n/// @title StandardBounties\n/// @dev A contract for issuing bounties on Ethereum paying in ETH, ERC20, or ERC721 tokens\n/// @author Mark Beylin <mark.beylin@consensys.net>, Gonçalo Sá <goncalo.sa@consensys.net>, Kevin Owocki <kevin.owocki@consensys.net>, Ricardo Guilherme Schmidt (@3esmit), Matt Garnett <matt.garnett@consensys.net>, Craig Williams <craig.williams@consensys.net>\ncontract StandardBounties {\n\n  using SafeMath for uint256;\n\n  /*\n   * Structs\n   */\n\n  struct Bounty {\n    address payable [] issuers; // An array of individuals who have complete control over the bounty, and can edit any of its parameters\n    address [] approvers; // An array of individuals who are allowed to accept the fulfillments for a particular bounty\n    uint deadline; // The Unix timestamp before which all submissions must be made, and after which refunds may be processed\n    address token; // The address of the token associated with the bounty (should be disregarded if the tokenVersion is 0)\n    uint tokenVersion; // The version of the token being used for the bounty (0 for ETH, 20 for ERC20, 721 for ERC721)\n    uint balance; // The number of tokens which the bounty is able to pay out or refund\n    bool hasPaidOut; // A boolean storing whether or not the bounty has paid out at least once, meaning refunds are no longer allowed\n    Fulfillment [] fulfillments; // An array of Fulfillments which store the various submissions which have been made to the bounty\n    Contribution [] contributions; // An array of Contributions which store the contributions which have been made to the bounty\n  }\n\n  struct Fulfillment {\n    address payable [] fulfillers; // An array of addresses who should receive payouts for a given submission\n    address submitter; // The address of the individual who submitted the fulfillment, who is able to update the submission as needed\n  }\n\n  struct Contribution {\n    address payable contributor; // The address of the individual who contributed\n    uint amount; // The amount of tokens the user contributed\n    bool refunded; // A boolean storing whether or not the contribution has been refunded yet\n  }\n\n  /*\n   * Storage\n   */\n\n  uint public numBounties; // An integer storing the total number of bounties in the contract\n  mapping(uint => Bounty) public bounties; // A mapping of bountyIDs to bounties\n  mapping (uint => mapping (uint => bool)) public tokenBalances; // A mapping of bountyIds to tokenIds to booleans, storing whether a given bounty has a given ERC721 token in its balance\n\n\n  address public owner; // The address of the individual who's allowed to set the metaTxRelayer address\n  address public metaTxRelayer; // The address of the meta transaction relayer whose _sender is automatically trusted for all contract calls\n\n  bool public callStarted; // Ensures mutex for the entire contract\n\n  /*\n   * Modifiers\n   */\n\n  modifier callNotStarted(){\n    require(!callStarted);\n    callStarted = true;\n    _;\n    callStarted = false;\n  }\n\n  modifier validateBountyArrayIndex(\n    uint _index)\n  {\n    require(_index < numBounties);\n    _;\n  }\n\n  modifier validateContributionArrayIndex(\n    uint _bountyId,\n    uint _index)\n  {\n    require(_index < bounties[_bountyId].contributions.length);\n    _;\n  }\n\n  modifier validateFulfillmentArrayIndex(\n    uint _bountyId,\n    uint _index)\n  {\n    require(_index < bounties[_bountyId].fulfillments.length);\n    _;\n  }\n\n  modifier validateIssuerArrayIndex(\n    uint _bountyId,\n    uint _index)\n  {\n    require(_index < bounties[_bountyId].issuers.length);\n    _;\n  }\n\n  modifier validateApproverArrayIndex(\n    uint _bountyId,\n    uint _index)\n  {\n    require(_index < bounties[_bountyId].approvers.length);\n    _;\n  }\n\n  modifier onlyIssuer(\n  address _sender,\n  uint _bountyId,\n  uint _issuerId)\n  {\n  require(_sender == bounties[_bountyId].issuers[_issuerId]);\n  _;\n  }\n\n  modifier onlySubmitter(\n    address _sender,\n    uint _bountyId,\n    uint _fulfillmentId)\n  {\n    require(_sender ==\n            bounties[_bountyId].fulfillments[_fulfillmentId].submitter);\n    _;\n  }\n\n  modifier onlyContributor(\n  address _sender,\n  uint _bountyId,\n  uint _contributionId)\n  {\n    require(_sender ==\n            bounties[_bountyId].contributions[_contributionId].contributor);\n    _;\n  }\n\n  modifier isApprover(\n    address _sender,\n    uint _bountyId,\n    uint _approverId)\n  {\n    require(_sender == bounties[_bountyId].approvers[_approverId]);\n    _;\n  }\n\n  modifier hasNotPaid(\n    uint _bountyId)\n  {\n    require(!bounties[_bountyId].hasPaidOut);\n    _;\n  }\n\n  modifier hasNotRefunded(\n    uint _bountyId,\n    uint _contributionId)\n  {\n    require(!bounties[_bountyId].contributions[_contributionId].refunded);\n    _;\n  }\n\n  modifier senderIsValid(\n    address _sender)\n  {\n    require(msg.sender == _sender || msg.sender == metaTxRelayer);\n    _;\n  }\n\n /*\n  * Public functions\n  */\n\n  constructor() public {\n    // The owner of the contract is automatically designated to be the deployer of the contract\n    owner = msg.sender;\n  }\n\n  /// @dev setMetaTxRelayer(): Sets the address of the meta transaction relayer\n  /// @param _relayer the address of the relayer\n  function setMetaTxRelayer(address _relayer)\n    external\n  {\n    require(msg.sender == owner); // Checks that only the owner can call\n    require(metaTxRelayer == address(0)); // Ensures the meta tx relayer can only be set once\n    metaTxRelayer = _relayer;\n  }\n\n  /// @dev issueBounty(): creates a new bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _issuers the array of addresses who will be the issuers of the bounty\n  /// @param _approvers the array of addresses who will be the approvers of the bounty\n  /// @param _data the IPFS hash representing the JSON object storing the details of the bounty (see docs for schema details)\n  /// @param _deadline the timestamp which will become the deadline of the bounty\n  /// @param _token the address of the token which will be used for the bounty\n  /// @param _tokenVersion the version of the token being used for the bounty (0 for ETH, 20 for ERC20, 721 for ERC721)\n  function issueBounty(\n    address payable _sender,\n    address payable [] memory _issuers,\n    address [] memory _approvers,\n    string memory _data,\n    uint _deadline,\n    address _token,\n    uint _tokenVersion)\n    public\n    senderIsValid(_sender)\n    returns (uint)\n  {\n    require(_tokenVersion == 0 || _tokenVersion == 20 || _tokenVersion == 721); // Ensures a bounty can only be issued with a valid token version\n    require(_issuers.length > 0 || _approvers.length > 0); // Ensures there's at least 1 issuer or approver, so funds don't get stuck\n\n    uint bountyId = numBounties; // The next bounty's index will always equal the number of existing bounties\n\n    Bounty storage newBounty = bounties[bountyId];\n    newBounty.issuers = _issuers;\n    newBounty.approvers = _approvers;\n    newBounty.deadline = _deadline;\n    newBounty.tokenVersion = _tokenVersion;\n\n    if (_tokenVersion != 0) {\n      newBounty.token = _token;\n    }\n\n    numBounties = numBounties.add(1); // Increments the number of bounties, since a new one has just been added\n\n    emit BountyIssued(bountyId,\n                      _sender,\n                      _issuers,\n                      _approvers,\n                      _data, // Instead of storing the string on-chain, it is emitted within the event for easy off-chain consumption\n                      _deadline,\n                      _token,\n                      _tokenVersion);\n\n    return (bountyId);\n  }\n\n  /// @param _depositAmount the amount of tokens being deposited to the bounty, which will create a new contribution to the bounty\n\n\n  function issueAndContribute(\n    address payable _sender,\n    address payable [] memory _issuers,\n    address [] memory _approvers,\n    string memory _data,\n    uint _deadline,\n    address _token,\n    uint _tokenVersion,\n    uint _depositAmount)\n    public\n    payable\n    returns(uint)\n  {\n    uint bountyId = issueBounty(_sender, _issuers, _approvers, _data, _deadline, _token, _tokenVersion);\n\n    contribute(_sender, bountyId, _depositAmount);\n\n    return (bountyId);\n  }\n\n\n  /// @dev contribute(): Allows users to contribute tokens to a given bounty.\n  ///                    Contributing merits no privelages to administer the\n  ///                    funds in the bounty or accept submissions. Contributions\n  ///                    are refundable but only on the condition that the deadline\n  ///                    has elapsed, and the bounty has not yet paid out any funds.\n  ///                    All funds deposited in a bounty are at the mercy of a\n  ///                    bounty's issuers and approvers, so please be careful!\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _amount the amount of tokens being contributed\n  function contribute(\n    address payable _sender,\n    uint _bountyId,\n    uint _amount)\n    public\n    payable\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    callNotStarted\n  {\n    require(_amount > 0); // Contributions of 0 tokens or token ID 0 should fail\n\n    bounties[_bountyId].contributions.push(\n      Contribution(_sender, _amount, false)); // Adds the contribution to the bounty\n\n    if (bounties[_bountyId].tokenVersion == 0){\n\n      bounties[_bountyId].balance = bounties[_bountyId].balance.add(_amount); // Increments the balance of the bounty\n\n      require(msg.value == _amount);\n    } else if (bounties[_bountyId].tokenVersion == 20) {\n\n      bounties[_bountyId].balance = bounties[_bountyId].balance.add(_amount); // Increments the balance of the bounty\n\n      require(msg.value == 0); // Ensures users don't accidentally send ETH alongside a token contribution, locking up funds\n      require(ERC20Token(bounties[_bountyId].token).transferFrom(_sender,\n                                                                 address(this),\n                                                                 _amount));\n    } else if (bounties[_bountyId].tokenVersion == 721) {\n      tokenBalances[_bountyId][_amount] = true; // Adds the 721 token to the balance of the bounty\n\n\n      require(msg.value == 0); // Ensures users don't accidentally send ETH alongside a token contribution, locking up funds\n      ERC721BasicToken(bounties[_bountyId].token).transferFrom(_sender,\n                                                               address(this),\n                                                               _amount);\n    } else {\n      revert();\n    }\n\n    emit ContributionAdded(_bountyId,\n                           bounties[_bountyId].contributions.length - 1, // The new contributionId\n                           _sender,\n                           _amount);\n  }\n\n  /// @dev refundContribution(): Allows users to refund the contributions they've\n  ///                            made to a particular bounty, but only if the bounty\n  ///                            has not yet paid out, and the deadline has elapsed.\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _contributionId the index of the contribution being refunded\n  function refundContribution(\n    address _sender,\n    uint _bountyId,\n    uint _contributionId)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateContributionArrayIndex(_bountyId, _contributionId)\n    onlyContributor(_sender, _bountyId, _contributionId)\n    hasNotPaid(_bountyId)\n    hasNotRefunded(_bountyId, _contributionId)\n    callNotStarted\n  {\n    require(now > bounties[_bountyId].deadline); // Refunds may only be processed after the deadline has elapsed\n\n    Contribution storage contribution =\n      bounties[_bountyId].contributions[_contributionId];\n\n    contribution.refunded = true;\n\n    transferTokens(_bountyId, contribution.contributor, contribution.amount); // Performs the disbursal of tokens to the contributor\n\n    emit ContributionRefunded(_bountyId, _contributionId);\n  }\n\n  /// @dev refundMyContributions(): Allows users to refund their contributions in bulk\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _contributionIds the array of indexes of the contributions being refunded\n  function refundMyContributions(\n    address _sender,\n    uint _bountyId,\n    uint [] memory _contributionIds)\n    public\n    senderIsValid(_sender)\n  {\n    for (uint i = 0; i < _contributionIds.length; i++){\n      refundContribution(_sender, _bountyId, _contributionIds[i]);\n    }\n  }\n\n  /// @dev refundContributions(): Allows users to refund their contributions in bulk\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is making the call\n  /// @param _contributionIds the array of indexes of the contributions being refunded\n  function refundContributions(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    uint [] memory _contributionIds)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n    callNotStarted\n  {\n    for (uint i = 0; i < _contributionIds.length; i++){\n      require(_contributionIds[i] < bounties[_bountyId].contributions.length);\n\n      Contribution storage contribution =\n        bounties[_bountyId].contributions[_contributionIds[i]];\n\n      require(!contribution.refunded);\n\n      contribution.refunded = true;\n\n      transferTokens(_bountyId, contribution.contributor, contribution.amount); // Performs the disbursal of tokens to the contributor\n    }\n\n    emit ContributionsRefunded(_bountyId, _sender, _contributionIds);\n  }\n\n  /// @dev drainBounty(): Allows an issuer to drain the funds from the bounty\n  /// @notice when using this function, if an issuer doesn't drain the entire balance, some users may be able to refund their contributions, while others may not (which is unfair to them). Please use it wisely, only when necessary\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is making the call\n  /// @param _amounts an array of amounts of tokens to be sent. The length of the array should be 1 if the bounty is in ETH or ERC20 tokens. If it's an ERC721 bounty, the array should be the list of tokenIDs.\n  function drainBounty(\n    address payable _sender,\n    uint _bountyId,\n    uint _issuerId,\n    uint [] memory _amounts)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n    callNotStarted\n  {\n    if (bounties[_bountyId].tokenVersion == 0 || bounties[_bountyId].tokenVersion == 20){\n      require(_amounts.length == 1); // ensures there's only 1 amount of tokens to be returned\n      require(_amounts[0] <= bounties[_bountyId].balance); // ensures an issuer doesn't try to drain the bounty of more tokens than their balance permits\n      transferTokens(_bountyId, _sender, _amounts[0]); // Performs the draining of tokens to the issuer\n    } else {\n      for (uint i = 0; i < _amounts.length; i++){\n        require(tokenBalances[_bountyId][_amounts[i]]);// ensures an issuer doesn't try to drain the bounty of a token it doesn't have in its balance\n        transferTokens(_bountyId, _sender, _amounts[i]);\n      }\n    }\n\n    emit BountyDrained(_bountyId, _sender, _amounts);\n  }\n\n  /// @dev performAction(): Allows users to perform any generalized action\n  ///                       associated with a particular bounty, such as applying for it\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _data the IPFS hash corresponding to a JSON object which contains the details of the action being performed (see docs for schema details)\n  function performAction(\n    address _sender,\n    uint _bountyId,\n    string memory _data)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n  {\n    emit ActionPerformed(_bountyId, _sender, _data); // The _data string is emitted in an event for easy off-chain consumption\n  }\n\n  /// @dev fulfillBounty(): Allows users to fulfill the bounty to get paid out\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _fulfillers the array of addresses which will receive payouts for the submission\n  /// @param _data the IPFS hash corresponding to a JSON object which contains the details of the submission (see docs for schema details)\n  function fulfillBounty(\n    address _sender,\n    uint _bountyId,\n    address payable [] memory  _fulfillers,\n    string memory _data)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n  {\n    require(now < bounties[_bountyId].deadline); // Submissions are only allowed to be made before the deadline\n    require(_fulfillers.length > 0); // Submissions with no fulfillers would mean no one gets paid out\n\n    bounties[_bountyId].fulfillments.push(Fulfillment(_fulfillers, _sender));\n\n    emit BountyFulfilled(_bountyId,\n                         (bounties[_bountyId].fulfillments.length - 1),\n                         _fulfillers,\n                         _data, // The _data string is emitted in an event for easy off-chain consumption\n                         _sender);\n  }\n\n  /// @dev updateFulfillment(): Allows the submitter of a fulfillment to update their submission\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _fulfillmentId the index of the fulfillment\n  /// @param _fulfillers the new array of addresses which will receive payouts for the submission\n  /// @param _data the new IPFS hash corresponding to a JSON object which contains the details of the submission (see docs for schema details)\n  function updateFulfillment(\n  address _sender,\n  uint _bountyId,\n  uint _fulfillmentId,\n  address payable [] memory _fulfillers,\n  string memory _data)\n  public\n  senderIsValid(_sender)\n  validateBountyArrayIndex(_bountyId)\n  validateFulfillmentArrayIndex(_bountyId, _fulfillmentId)\n  onlySubmitter(_sender, _bountyId, _fulfillmentId) // Only the original submitter of a fulfillment may update their submission\n  {\n    bounties[_bountyId].fulfillments[_fulfillmentId].fulfillers = _fulfillers;\n    emit FulfillmentUpdated(_bountyId,\n                            _fulfillmentId,\n                            _fulfillers,\n                            _data); // The _data string is emitted in an event for easy off-chain consumption\n  }\n\n  /// @dev acceptFulfillment(): Allows any of the approvers to accept a given submission\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _fulfillmentId the index of the fulfillment to be accepted\n  /// @param _approverId the index of the approver which is making the call\n  /// @param _tokenAmounts the array of token amounts which will be paid to the\n  ///                      fulfillers, whose length should equal the length of the\n  ///                      _fulfillers array of the submission. If the bounty pays\n  ///                      in ERC721 tokens, then these should be the token IDs\n  ///                      being sent to each of the individual fulfillers\n  function acceptFulfillment(\n    address _sender,\n    uint _bountyId,\n    uint _fulfillmentId,\n    uint _approverId,\n    uint[] memory _tokenAmounts)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateFulfillmentArrayIndex(_bountyId, _fulfillmentId)\n    isApprover(_sender, _bountyId, _approverId)\n    callNotStarted\n  {\n    // now that the bounty has paid out at least once, refunds are no longer possible\n    bounties[_bountyId].hasPaidOut = true;\n\n    Fulfillment storage fulfillment =\n      bounties[_bountyId].fulfillments[_fulfillmentId];\n\n    require(_tokenAmounts.length == fulfillment.fulfillers.length); // Each fulfiller should get paid some amount of tokens (this can be 0)\n\n    for (uint256 i = 0; i < fulfillment.fulfillers.length; i++){\n        if (_tokenAmounts[i] > 0) {\n          // for each fulfiller associated with the submission\n          transferTokens(_bountyId, fulfillment.fulfillers[i], _tokenAmounts[i]);\n        }\n    }\n    emit FulfillmentAccepted(_bountyId,\n                             _fulfillmentId,\n                             _sender,\n                             _tokenAmounts);\n  }\n\n  /// @dev fulfillAndAccept(): Allows any of the approvers to fulfill and accept a submission simultaneously\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _fulfillers the array of addresses which will receive payouts for the submission\n  /// @param _data the IPFS hash corresponding to a JSON object which contains the details of the submission (see docs for schema details)\n  /// @param _approverId the index of the approver which is making the call\n  /// @param _tokenAmounts the array of token amounts which will be paid to the\n  ///                      fulfillers, whose length should equal the length of the\n  ///                      _fulfillers array of the submission. If the bounty pays\n  ///                      in ERC721 tokens, then these should be the token IDs\n  ///                      being sent to each of the individual fulfillers\n  function fulfillAndAccept(\n    address _sender,\n    uint _bountyId,\n    address payable [] memory _fulfillers,\n    string memory _data,\n    uint _approverId,\n    uint[] memory _tokenAmounts)\n    public\n    senderIsValid(_sender)\n  {\n    // first fulfills the bounty on behalf of the fulfillers\n    fulfillBounty(_sender, _bountyId, _fulfillers, _data);\n\n    // then accepts the fulfillment\n    acceptFulfillment(_sender,\n                      _bountyId,\n                      bounties[_bountyId].fulfillments.length - 1,\n                      _approverId,\n                      _tokenAmounts);\n  }\n\n\n\n  /// @dev changeBounty(): Allows any of the issuers to change the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _issuers the new array of addresses who will be the issuers of the bounty\n  /// @param _approvers the new array of addresses who will be the approvers of the bounty\n  /// @param _data the new IPFS hash representing the JSON object storing the details of the bounty (see docs for schema details)\n  /// @param _deadline the new timestamp which will become the deadline of the bounty\n  function changeBounty(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _issuers,\n    address payable [] memory _approvers,\n    string memory _data,\n    uint _deadline)\n    public\n    senderIsValid(_sender)\n  {\n    require(_bountyId < numBounties); // makes the validateBountyArrayIndex modifier in-line to avoid stack too deep errors\n    require(_issuerId < bounties[_bountyId].issuers.length); // makes the validateIssuerArrayIndex modifier in-line to avoid stack too deep errors\n    require(_sender == bounties[_bountyId].issuers[_issuerId]); // makes the onlyIssuer modifier in-line to avoid stack too deep errors\n\n    require(_issuers.length > 0 || _approvers.length > 0); // Ensures there's at least 1 issuer or approver, so funds don't get stuck\n\n    bounties[_bountyId].issuers = _issuers;\n    bounties[_bountyId].approvers = _approvers;\n    bounties[_bountyId].deadline = _deadline;\n    emit BountyChanged(_bountyId,\n                       _sender,\n                       _issuers,\n                       _approvers,\n                       _data,\n                       _deadline);\n  }\n\n  /// @dev changeIssuer(): Allows any of the issuers to change a particular issuer of the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _issuerIdToChange the index of the issuer who is being changed\n  /// @param _newIssuer the address of the new issuer\n  function changeIssuer(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    uint _issuerIdToChange,\n    address payable _newIssuer)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateIssuerArrayIndex(_bountyId, _issuerIdToChange)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n  {\n    require(_issuerId < bounties[_bountyId].issuers.length || _issuerId == 0);\n\n    bounties[_bountyId].issuers[_issuerIdToChange] = _newIssuer;\n\n    emit BountyIssuersUpdated(_bountyId, _sender, bounties[_bountyId].issuers);\n  }\n\n  /// @dev changeApprover(): Allows any of the issuers to change a particular approver of the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _approverId the index of the approver who is being changed\n  /// @param _approver the address of the new approver\n  function changeApprover(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    uint _approverId,\n    address payable _approver)\n    external\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n    validateApproverArrayIndex(_bountyId, _approverId)\n  {\n    bounties[_bountyId].approvers[_approverId] = _approver;\n\n    emit BountyApproversUpdated(_bountyId, _sender, bounties[_bountyId].approvers);\n  }\n\n  /// @dev changeData(): Allows any of the issuers to change the data the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _data the new IPFS hash representing the JSON object storing the details of the bounty (see docs for schema details)\n  function changeData(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    string memory _data)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateIssuerArrayIndex(_bountyId, _issuerId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n  {\n    emit BountyDataChanged(_bountyId, _sender, _data); // The new _data is emitted within an event rather than being stored on-chain for minimized gas costs\n  }\n\n  /// @dev changeDeadline(): Allows any of the issuers to change the deadline the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _deadline the new timestamp which will become the deadline of the bounty\n  function changeDeadline(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    uint _deadline)\n    external\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateIssuerArrayIndex(_bountyId, _issuerId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n  {\n    bounties[_bountyId].deadline = _deadline;\n\n    emit BountyDeadlineChanged(_bountyId, _sender, _deadline);\n  }\n\n  /// @dev addIssuers(): Allows any of the issuers to add more issuers to the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _issuers the array of addresses to add to the list of valid issuers\n  function addIssuers(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _issuers)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateIssuerArrayIndex(_bountyId, _issuerId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n  {\n    for (uint i = 0; i < _issuers.length; i++){\n      bounties[_bountyId].issuers.push(_issuers[i]);\n    }\n\n    emit BountyIssuersUpdated(_bountyId, _sender, bounties[_bountyId].issuers);\n  }\n\n  /// @dev replaceIssuers(): Allows any of the issuers to replace the issuers of the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _issuers the array of addresses to replace the list of valid issuers\n  function replaceIssuers(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _issuers)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateIssuerArrayIndex(_bountyId, _issuerId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n  {\n    require(_issuers.length > 0 || bounties[_bountyId].approvers.length > 0); // Ensures there's at least 1 issuer or approver, so funds don't get stuck\n\n    bounties[_bountyId].issuers = _issuers;\n\n    emit BountyIssuersUpdated(_bountyId, _sender, bounties[_bountyId].issuers);\n  }\n\n  /// @dev addApprovers(): Allows any of the issuers to add more approvers to the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _approvers the array of addresses to add to the list of valid approvers\n  function addApprovers(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    address [] memory _approvers)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateIssuerArrayIndex(_bountyId, _issuerId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n  {\n    for (uint i = 0; i < _approvers.length; i++){\n      bounties[_bountyId].approvers.push(_approvers[i]);\n    }\n\n    emit BountyApproversUpdated(_bountyId, _sender, bounties[_bountyId].approvers);\n  }\n\n  /// @dev replaceApprovers(): Allows any of the issuers to replace the approvers of the bounty\n  /// @param _sender the sender of the transaction issuing the bounty (should be the same as msg.sender unless the txn is called by the meta tx relayer)\n  /// @param _bountyId the index of the bounty\n  /// @param _issuerId the index of the issuer who is calling the function\n  /// @param _approvers the array of addresses to replace the list of valid approvers\n  function replaceApprovers(\n    address _sender,\n    uint _bountyId,\n    uint _issuerId,\n    address [] memory _approvers)\n    public\n    senderIsValid(_sender)\n    validateBountyArrayIndex(_bountyId)\n    validateIssuerArrayIndex(_bountyId, _issuerId)\n    onlyIssuer(_sender, _bountyId, _issuerId)\n  {\n    require(bounties[_bountyId].issuers.length > 0 || _approvers.length > 0); // Ensures there's at least 1 issuer or approver, so funds don't get stuck\n    bounties[_bountyId].approvers = _approvers;\n\n    emit BountyApproversUpdated(_bountyId, _sender, bounties[_bountyId].approvers);\n  }\n\n  /// @dev getBounty(): Returns the details of the bounty\n  /// @param _bountyId the index of the bounty\n  /// @return Returns a tuple for the bounty\n  function getBounty(uint _bountyId)\n    external\n    view\n    returns (Bounty memory)\n  {\n    return bounties[_bountyId];\n  }\n\n\n  function transferTokens(uint _bountyId, address payable _to, uint _amount)\n    internal\n  {\n    if (bounties[_bountyId].tokenVersion == 0){\n      require(_amount > 0); // Sending 0 tokens should throw\n      require(bounties[_bountyId].balance >= _amount);\n\n      bounties[_bountyId].balance = bounties[_bountyId].balance.sub(_amount);\n\n      _to.transfer(_amount);\n    } else if (bounties[_bountyId].tokenVersion == 20) {\n      require(_amount > 0); // Sending 0 tokens should throw\n      require(bounties[_bountyId].balance >= _amount);\n\n      bounties[_bountyId].balance = bounties[_bountyId].balance.sub(_amount);\n\n      require(ERC20Token(bounties[_bountyId].token).transfer(_to, _amount));\n    } else if (bounties[_bountyId].tokenVersion == 721) {\n      require(tokenBalances[_bountyId][_amount]);\n\n      tokenBalances[_bountyId][_amount] = false; // Removes the 721 token from the balance of the bounty\n\n      ERC721BasicToken(bounties[_bountyId].token).transferFrom(address(this),\n                                                               _to,\n                                                               _amount);\n    } else {\n      revert();\n    }\n  }\n\n  /*\n   * Events\n   */\n\n  event BountyIssued(uint _bountyId, address payable _creator, address payable [] _issuers, address [] _approvers, string _data, uint _deadline, address _token, uint _tokenVersion);\n  event ContributionAdded(uint _bountyId, uint _contributionId, address payable _contributor, uint _amount);\n  event ContributionRefunded(uint _bountyId, uint _contributionId);\n  event ContributionsRefunded(uint _bountyId, address _issuer, uint [] _contributionIds);\n  event BountyDrained(uint _bountyId, address _issuer, uint [] _amounts);\n  event ActionPerformed(uint _bountyId, address _fulfiller, string _data);\n  event BountyFulfilled(uint _bountyId, uint _fulfillmentId, address payable [] _fulfillers, string _data, address _submitter);\n  event FulfillmentUpdated(uint _bountyId, uint _fulfillmentId, address payable [] _fulfillers, string _data);\n  event FulfillmentAccepted(uint _bountyId, uint  _fulfillmentId, address _approver, uint[] _tokenAmounts);\n  event BountyChanged(uint _bountyId, address _changer, address payable [] _issuers, address payable [] _approvers, string _data, uint _deadline);\n  event BountyIssuersUpdated(uint _bountyId, address _changer, address payable [] _issuers);\n  event BountyApproversUpdated(uint _bountyId, address _changer, address [] _approvers);\n  event BountyDataChanged(uint _bountyId, address _changer, string _data);\n  event BountyDeadlineChanged(uint _bountyId, address _changer, uint _deadline);\n}\n"
    },
    "contracts/5/standard_bounties/v2/inherited/ERC20Token.sol": {
      "content": "/*\nYou should inherit from StandardToken or, for a token like you would want to\ndeploy in something like Mist, see HumanStandardToken.sol.\n(This implements ONLY the standard functions and NOTHING else.\nIf you deploy this, you won't have anything useful.)\n\nImplements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20\n.*/\npragma solidity 0.5.16;\n\nimport \"./Token.sol\";\n\ncontract ERC20Token is Token {\n\n    function transfer(address _to, uint256 _value) public returns (bool success) {\n        //Default assumes totalSupply can't be over max (2^256 - 1).\n        //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.\n        //Replace the if with this one instead.\n        //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {\n        if (balances[msg.sender] >= _value && _value > 0) {\n            balances[msg.sender] -= _value;\n            balances[_to] += _value;\n            emit Transfer(msg.sender, _to, _value);\n            return true;\n        } else { return false; }\n    }\n\n    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {\n        //same as above. Replace this line with the following if you want to protect against wrapping uints.\n        //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {\n        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {\n            balances[_to] += _value;\n            balances[_from] -= _value;\n            allowed[_from][msg.sender] -= _value;\n            emit Transfer(_from, _to, _value);\n            return true;\n        } else { return false; }\n    }\n\n    function balanceOf(address _owner) view public returns (uint256 balance) {\n        return balances[_owner];\n    }\n\n    function approve(address _spender, uint256 _value) public returns (bool success) {\n        allowed[msg.sender][_spender] = _value;\n        emit Approval(msg.sender, _spender, _value);\n        return true;\n    }\n\n    function allowance(address _owner, address _spender) view public returns (uint256 remaining) {\n      return allowed[_owner][_spender];\n    }\n\n    mapping (address => uint256) balances;\n    mapping (address => mapping (address => uint256)) allowed;\n}\n"
    },
    "contracts/5/standard_bounties/v2/inherited/Token.sol": {
      "content": "// Abstract contract for the full ERC 20 Token standard\n// https://github.com/ethereum/EIPs/issues/20\npragma solidity 0.5.16;\n\ncontract Token {\n    /* This is a slight change to the ERC20 base standard.\n    function totalSupply() pure returns (uint256 supply);\n    is replaced with:\n    uint256 public totalSupply;\n    This automatically creates a getter function for the totalSupply.\n    This is moved to the base contract since public getter functions are not\n    currently recognised as an implementation of the matching abstract\n    function by the compiler.\n    */\n    /// total amount of tokens\n    uint256 public totalSupply;\n\n    /// @param _owner The address from which the balance will be retrieved\n    /// @return The balance\n    function balanceOf(address _owner) view public returns (uint256 balance);\n\n    /// @notice send `_value` token to `_to` from `msg.sender`\n    /// @param _to The address of the recipient\n    /// @param _value The amount of token to be transferred\n    /// @return Whether the transfer was successful or not\n    function transfer(address _to, uint256 _value) public returns (bool success);\n\n    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`\n    /// @param _from The address of the sender\n    /// @param _to The address of the recipient\n    /// @param _value The amount of token to be transferred\n    /// @return Whether the transfer was successful or not\n    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);\n\n    /// @notice `msg.sender` approves `_spender` to spend `_value` tokens\n    /// @param _spender The address of the account able to transfer the tokens\n    /// @param _value The amount of tokens to be approved for transfer\n    /// @return Whether the approval was successful or not\n    function approve(address _spender, uint256 _value) public returns (bool success);\n\n    /// @param _owner The address of the account owning tokens\n    /// @param _spender The address of the account able to transfer the tokens\n    /// @return Amount of remaining tokens allowed to spent\n    function allowance(address _owner, address _spender) public view returns (uint256 remaining);\n\n    event Transfer(address _from, address _to, uint256 _value);\n    event Approval(address _owner, address _spender, uint256 _value);\n}\n"
    },
    "contracts/5/standard_bounties/v2/inherited/ERC721Basic.sol": {
      "content": " pragma solidity 0.5.16;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * Utility library of inline functions on addresses\n */\nlibrary AddressUtils {\n\n  /**\n   * Returns whether the target address is a contract\n   * @dev This function will return false if invoked during the constructor of a contract,\n   * as the code is not actually created until after the constructor finishes.\n   * @param addr address to check\n   * @return whether the target address is a contract\n   */\n  function isContract(address addr) internal view returns (bool) {\n    uint256 size;\n    // XXX Currently there is no better way to check if there is a contract in an address\n    // than to check the size of the code at that address.\n    // See https://ethereum.stackexchange.com/a/14016/36603\n    // for more details about how this works.\n    // TODO Check this again before the Serenity release, because all addresses will be\n    // contracts then.\n    // solium-disable-next-line security/no-inline-assembly\n    assembly { size := extcodesize(addr) }\n    return size > 0;\n  }\n\n}\n\n/**\n * @title ERC165\n * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md\n */\ninterface ERC165 {\n\n  /**\n   * @notice Query if a contract implements an interface\n   * @param _interfaceId The interface identifier, as specified in ERC-165\n   * @dev Interface identification is specified in ERC-165. This function\n   * uses less than 30,000 gas.\n   */\n  function supportsInterface(bytes4 _interfaceId)\n    external\n    view\n    returns (bool);\n}\n\n\n/**\n * @title SupportsInterfaceWithLookup\n * @author Matt Condon (@shrugs)\n * @dev Implements ERC165 using a lookup table.\n */\ncontract SupportsInterfaceWithLookup is ERC165 {\n  bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;\n  /**\n   * 0x01ffc9a7 ===\n   *   bytes4(keccak256('supportsInterface(bytes4)'))\n   */\n\n  /**\n   * @dev a mapping of interface id to whether or not it's supported\n   */\n  mapping(bytes4 => bool) internal supportedInterfaces;\n\n  /**\n   * @dev A contract implementing SupportsInterfaceWithLookup\n   * implement ERC165 itself\n   */\n  constructor()\n    public\n  {\n    _registerInterface(InterfaceId_ERC165);\n  }\n\n  /**\n   * @dev implement supportsInterface(bytes4) using a lookup table\n   */\n  function supportsInterface(bytes4 _interfaceId)\n    external\n    view\n    returns (bool)\n  {\n    return supportedInterfaces[_interfaceId];\n  }\n\n  /**\n   * @dev private method for registering an interface\n   */\n  function _registerInterface(bytes4 _interfaceId)\n    internal\n  {\n    require(_interfaceId != 0xffffffff);\n    supportedInterfaces[_interfaceId] = true;\n  }\n}\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ncontract ERC721Receiver {\n  /**\n   * @dev Magic value to be returned upon successful reception of an NFT\n   *  Equals to `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`,\n   *  which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`\n   */\n  bytes4 internal constant ERC721_RECEIVED = 0xf0b9e5ba;\n\n  /**\n   * @notice Handle the receipt of an NFT\n   * @dev The ERC721 smart contract calls this function on the recipient\n   * after a `safetransfer`. This function MAY throw to revert and reject the\n   * transfer. This function MUST use 50,000 gas or less. Return of other\n   * than the magic value MUST result in the transaction being reverted.\n   * Note: the contract address is always the message sender.\n   * @param _from The sending address\n   * @param _tokenId The NFT identifier which is being transfered\n   * @param _data Additional data with no specified format\n   * @return `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`\n   */\n  function onERC721Received(\n    address _from,\n    uint256 _tokenId,\n    bytes memory _data\n  )\n    public\n    returns(bytes4);\n}\n\n/**\n * @title ERC721 Non-Fungible Token Standard basic interface\n * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md\n */\ncontract ERC721Basic is ERC165 {\n  event Transfer(\n    address  _from,\n    address  _to,\n    uint256  _tokenId\n  );\n  event Approval(\n    address  _owner,\n    address  _approved,\n    uint256  _tokenId\n  );\n  event ApprovalForAll(\n    address  _owner,\n    address  _operator,\n    bool _approved\n  );\n\n  function balanceOf(address _owner) public view returns (uint256 _balance);\n  function ownerOf(uint256 _tokenId) public view returns (address _owner);\n  function exists(uint256 _tokenId) public view returns (bool _exists);\n\n  function approve(address _to, uint256 _tokenId) public;\n  function getApproved(uint256 _tokenId)\n    public view returns (address _operator);\n\n  function setApprovalForAll(address _operator, bool _approved) public;\n  function isApprovedForAll(address _owner, address _operator)\n    public view returns (bool);\n\n  function transferFrom(address _from, address _to, uint256 _tokenId) public;\n  function safeTransferFrom(address _from, address _to, uint256 _tokenId)\n    public;\n\n  function safeTransferFrom(\n    address _from,\n    address _to,\n    uint256 _tokenId,\n    bytes memory _data\n  )\n    public;\n}\n\n/**\n * @title ERC721 Non-Fungible Token Standard basic implementation\n * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md\n */\ncontract ERC721BasicToken is SupportsInterfaceWithLookup, ERC721Basic {\n\n  bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd;\n  /*\n   * 0x80ac58cd ===\n   *   bytes4(keccak256('balanceOf(address)')) ^\n   *   bytes4(keccak256('ownerOf(uint256)')) ^\n   *   bytes4(keccak256('approve(address,uint256)')) ^\n   *   bytes4(keccak256('getApproved(uint256)')) ^\n   *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^\n   *   bytes4(keccak256('isApprovedForAll(address,address)')) ^\n   *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^\n   *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^\n   *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))\n   */\n\n  bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79;\n  /*\n   * 0x4f558e79 ===\n   *   bytes4(keccak256('exists(uint256)'))\n   */\n\n  using SafeMath for uint256;\n  using AddressUtils for address;\n\n  // Equals to `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`\n  // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`\n  bytes4 private constant ERC721_RECEIVED = 0xf0b9e5ba;\n\n  // Mapping from token ID to owner\n  mapping (uint256 => address) internal tokenOwner;\n\n  // Mapping from token ID to approved address\n  mapping (uint256 => address) internal tokenApprovals;\n\n  // Mapping from owner to number of owned token\n  mapping (address => uint256) internal ownedTokensCount;\n\n  // Mapping from owner to operator approvals\n  mapping (address => mapping (address => bool)) internal operatorApprovals;\n\n\n  uint public testint;\n  /**\n   * @dev Guarantees msg.sender is owner of the given token\n   * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender\n   */\n  modifier onlyOwnerOf(uint256 _tokenId) {\n    require(ownerOf(_tokenId) == msg.sender);\n    _;\n  }\n\n  /**\n   * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator\n   * @param _tokenId uint256 ID of the token to validate\n   */\n  modifier canTransfer(uint256 _tokenId) {\n    require(isApprovedOrOwner(msg.sender, _tokenId));\n    _;\n  }\n\n  constructor()\n    public\n  {\n    // register the supported interfaces to conform to ERC721 via ERC165\n    _registerInterface(InterfaceId_ERC721);\n    _registerInterface(InterfaceId_ERC721Exists);\n  }\n\n  /**\n   * @dev Gets the balance of the specified address\n   * @param _owner address to query the balance of\n   * @return uint256 representing the amount owned by the passed address\n   */\n  function balanceOf(address _owner) public view returns (uint256) {\n    require(_owner != address(0));\n    return ownedTokensCount[_owner];\n  }\n\n  /**\n   * @dev Gets the owner of the specified token ID\n   * @param _tokenId uint256 ID of the token to query the owner of\n   * @return owner address currently marked as the owner of the given token ID\n   */\n  function ownerOf(uint256 _tokenId) public view returns (address) {\n    address owner = tokenOwner[_tokenId];\n    require(owner != address(0));\n    return owner;\n  }\n\n  /**\n   * @dev Returns whether the specified token exists\n   * @param _tokenId uint256 ID of the token to query the existence of\n   * @return whether the token exists\n   */\n  function exists(uint256 _tokenId) public view returns (bool) {\n    address owner = tokenOwner[_tokenId];\n    return owner != address(0);\n  }\n\n  /**\n   * @dev Approves another address to transfer the given token ID\n   * The zero address indicates there is no approved address.\n   * There can only be one approved address per token at a given time.\n   * Can only be called by the token owner or an approved operator.\n   * @param _to address to be approved for the given token ID\n   * @param _tokenId uint256 ID of the token to be approved\n   */\n  function approve(address _to, uint256 _tokenId) public {\n    address owner = ownerOf(_tokenId);\n    require(_to != owner);\n    require(msg.sender == owner || isApprovedForAll(owner, msg.sender));\n\n    tokenApprovals[_tokenId] = _to;\n    emit Approval(owner, _to, _tokenId);\n  }\n\n  /**\n   * @dev Gets the approved address for a token ID, or zero if no address set\n   * @param _tokenId uint256 ID of the token to query the approval of\n   * @return address currently approved for the given token ID\n   */\n  function getApproved(uint256 _tokenId) public view returns (address) {\n    return tokenApprovals[_tokenId];\n  }\n\n  /**\n   * @dev Sets or unsets the approval of a given operator\n   * An operator is allowed to transfer all tokens of the sender on their behalf\n   * @param _to operator address to set the approval\n   * @param _approved representing the status of the approval to be set\n   */\n  function setApprovalForAll(address _to, bool _approved) public {\n    require(_to != msg.sender);\n    operatorApprovals[msg.sender][_to] = _approved;\n    emit ApprovalForAll(msg.sender, _to, _approved);\n  }\n\n  /**\n   * @dev Tells whether an operator is approved by a given owner\n   * @param _owner owner address which you want to query the approval of\n   * @param _operator operator address which you want to query the approval of\n   * @return bool whether the given operator is approved by the given owner\n   */\n  function isApprovedForAll(\n    address _owner,\n    address _operator\n  )\n    public\n    view\n    returns (bool)\n  {\n    return operatorApprovals[_owner][_operator];\n  }\n\n  /**\n   * @dev Transfers the ownership of a given token ID to another address\n   * Usage of this method is discouraged, use `safeTransferFrom` whenever possible\n   * Requires the msg sender to be the owner, approved, or operator\n   * @param _from current owner of the token\n   * @param _to address to receive the ownership of the given token ID\n   * @param _tokenId uint256 ID of the token to be transferred\n  */\n  function transferFrom(\n    address _from,\n    address _to,\n    uint256 _tokenId\n  )\n    public\n    canTransfer(_tokenId)\n  {\n    require(_from != address(0));\n    require(_to != address(0));\n\n    clearApproval(_from, _tokenId);\n    removeTokenFrom(_from, _tokenId);\n    addTokenTo(_to, _tokenId);\n\n    emit Transfer(_from, _to, _tokenId);\n  }\n\n  /**\n   * @dev Safely transfers the ownership of a given token ID to another address\n   * If the target address is a contract, it must implement `onERC721Received`,\n   * which is called upon a safe transfer, and return the magic value\n   * `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`; otherwise,\n   * the transfer is reverted.\n   *\n   * Requires the msg sender to be the owner, approved, or operator\n   * @param _from current owner of the token\n   * @param _to address to receive the ownership of the given token ID\n   * @param _tokenId uint256 ID of the token to be transferred\n  */\n  function safeTransferFrom(\n    address _from,\n    address _to,\n    uint256 _tokenId\n  )\n    public\n    canTransfer(_tokenId)\n  {\n    // solium-disable-next-line arg-overflow\n    safeTransferFrom(_from, _to, _tokenId, \"\");\n  }\n\n  /**\n   * @dev Safely transfers the ownership of a given token ID to another address\n   * If the target address is a contract, it must implement `onERC721Received`,\n   * which is called upon a safe transfer, and return the magic value\n   * `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`; otherwise,\n   * the transfer is reverted.\n   * Requires the msg sender to be the owner, approved, or operator\n   * @param _from current owner of the token\n   * @param _to address to receive the ownership of the given token ID\n   * @param _tokenId uint256 ID of the token to be transferred\n   * @param _data bytes data to send along with a safe transfer check\n   */\n  function safeTransferFrom(\n    address _from,\n    address _to,\n    uint256 _tokenId,\n    bytes memory _data\n  )\n    public\n    canTransfer(_tokenId)\n  {\n    transferFrom(_from, _to, _tokenId);\n    // solium-disable-next-line arg-overflow\n    require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));\n  }\n\n  /**\n   * @dev Returns whether the given spender can transfer a given token ID\n   * @param _spender address of the spender to query\n   * @param _tokenId uint256 ID of the token to be transferred\n   * @return bool whether the msg.sender is approved for the given token ID,\n   *  is an operator of the owner, or is the owner of the token\n   */\n  function isApprovedOrOwner(\n    address _spender,\n    uint256 _tokenId\n  )\n    internal\n    view\n    returns (bool)\n  {\n    address owner = ownerOf(_tokenId);\n    // Disable solium check because of\n    // https://github.com/duaraghav8/Solium/issues/175\n    // solium-disable-next-line operator-whitespace\n    return (\n      _spender == owner ||\n      getApproved(_tokenId) == _spender ||\n      isApprovedForAll(owner, _spender)\n    );\n  }\n\n  /**\n   * @dev Internal function to mint a new token\n   * Reverts if the given token ID already exists\n   * @param _to The address that will own the minted token\n   * @param _tokenId uint256 ID of the token to be minted by the msg.sender\n   */\n  function _mint(address _to, uint256 _tokenId) internal {\n    require(_to != address(0));\n    addTokenTo(_to, _tokenId);\n    emit Transfer(address(0), _to, _tokenId);\n  }\n\n  /**\n   * @dev Internal function to burn a specific token\n   * Reverts if the token does not exist\n   * @param _tokenId uint256 ID of the token being burned by the msg.sender\n   */\n  function _burn(address _owner, uint256 _tokenId) internal {\n    clearApproval(_owner, _tokenId);\n    removeTokenFrom(_owner, _tokenId);\n    emit Transfer(_owner, address(0), _tokenId);\n  }\n\n  /**\n   * @dev Internal function to clear current approval of a given token ID\n   * Reverts if the given address is not indeed the owner of the token\n   * @param _owner owner of the token\n   * @param _tokenId uint256 ID of the token to be transferred\n   */\n  function clearApproval(address _owner, uint256 _tokenId) internal {\n    require(ownerOf(_tokenId) == _owner);\n    if (tokenApprovals[_tokenId] != address(0)) {\n      tokenApprovals[_tokenId] = address(0);\n    }\n  }\n\n  /**\n   * @dev Internal function to add a token ID to the list of a given address\n   * @param _to address representing the new owner of the given token ID\n   * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address\n   */\n  function addTokenTo(address _to, uint256 _tokenId) internal {\n    require(tokenOwner[_tokenId] == address(0));\n    tokenOwner[_tokenId] = _to;\n    ownedTokensCount[_to] = ownedTokensCount[_to].add(1);\n  }\n\n  /**\n   * @dev Internal function to remove a token ID from the list of a given address\n   * @param _from address representing the previous owner of the given token ID\n   * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address\n   */\n  function removeTokenFrom(address _from, uint256 _tokenId) internal {\n    require(ownerOf(_tokenId) == _from);\n    ownedTokensCount[_from] = ownedTokensCount[_from].sub(1);\n    tokenOwner[_tokenId] = address(0);\n  }\n\n  /**\n   * @dev Internal function to invoke `onERC721Received` on a target address\n   * The call is not executed if the target address is not a contract\n   * @param _from address representing the previous owner of the given token ID\n   * @param _to target address that will receive the tokens\n   * @param _tokenId uint256 ID of the token to be transferred\n   * @param _data bytes optional data to send along with the call\n   * @return whether the call correctly returned the expected magic value\n   */\n  function checkAndCallSafeTransfer(\n    address _from,\n    address _to,\n    uint256 _tokenId,\n    bytes memory _data\n  )\n    internal\n    returns (bool)\n  {\n    if (!_to.isContract()) {\n      return true;\n    }\n    bytes4 retval = ERC721Receiver(_to).onERC721Received(\n      _from, _tokenId, _data);\n    return (retval == ERC721_RECEIVED);\n  }\n}\n\ncontract ERC721BasicTokenMock is ERC721BasicToken {\n  function mint(address _to, uint256 _tokenId) public {\n    super._mint(_to, _tokenId);\n  }\n\n  function burn(uint256 _tokenId) public {\n    super._burn(ownerOf(_tokenId), _tokenId);\n  }\n}\n"
    },
    "@openzeppelin/contracts/math/SafeMath.sol": {
      "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c >= a, \"SafeMath: addition overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b <= a, \"SafeMath: subtraction overflow\");\n        uint256 c = a - b;\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Solidity only automatically asserts when dividing by 0\n        require(b > 0, \"SafeMath: division by zero\");\n        uint256 c = a / b;\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b != 0, \"SafeMath: modulo by zero\");\n        return a % b;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": {
      "content": "pragma solidity ^0.5.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using SafeMath for uint256;\n    using Address for address;\n\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        // solhint-disable-next-line max-line-length\n        require((value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value);\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves.\n\n        // A Solidity high level call has three parts:\n        //  1. The target address is checked to verify it contains contract code\n        //  2. The call itself is made, and success asserted\n        //  3. The return value is decoded, which in turn checks the size of the returned data.\n        // solhint-disable-next-line max-line-length\n        require(address(token).isContract(), \"SafeERC20: call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = address(token).call(data);\n        require(success, \"SafeERC20: low-level call failed\");\n\n        if (returndata.length > 0) { // Return data is optional\n            // solhint-disable-next-line max-line-length\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Collection of functions related to the address type,\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * This test is non-exhaustive, and there may be false-negatives: during the\n     * execution of a contract's constructor, its address will be reported as\n     * not containing a contract.\n     *\n     * > It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies in extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        // solhint-disable-next-line no-inline-assembly\n        assembly { size := extcodesize(account) }\n        return size > 0;\n    }\n}\n"
    },
    "contracts/5/Fantastic12Factory.sol": {
      "content": "pragma solidity 0.5.16;\n\nimport \"./Fantastic12.sol\";\n\ncontract Fantastic12Factory {\n  address public constant DAI_ADDR = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n\n  event CreateSquad(address indexed summoner, address squad);\n\n  function createSquad(address _summoner, uint256 _withdrawLimit, uint256 _consensusThreshold)\n    public\n    returns (Fantastic12 _squad)\n  {\n    _squad = new Fantastic12();\n    _squad.init(\n      _summoner,\n      DAI_ADDR,\n      _withdrawLimit,\n      _consensusThreshold\n    );\n    emit CreateSquad(_summoner, address(_squad));\n  }\n}"
    },
    "contracts/5/mocks/MockERC20.sol": {
      "content": "pragma solidity 0.5.16;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol\";\n\ncontract MockERC20 is ERC20Mintable {}"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol": {
      "content": "pragma solidity ^0.5.0;\n\nimport \"./ERC20.sol\";\nimport \"../../access/roles/MinterRole.sol\";\n\n/**\n * @dev Extension of `ERC20` that adds a set of accounts with the `MinterRole`,\n * which have permission to mint (create) new tokens as they see fit.\n *\n * At construction, the deployer of the contract is the only minter.\n */\ncontract ERC20Mintable is ERC20, MinterRole {\n    /**\n     * @dev See `ERC20._mint`.\n     *\n     * Requirements:\n     *\n     * - the caller must have the `MinterRole`.\n     */\n    function mint(address account, uint256 amount) public onlyMinter returns (bool) {\n        _mint(account, amount);\n        return true;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
      "content": "pragma solidity ^0.5.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the `IERC20` interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using `_mint`.\n * For a generic mechanism see `ERC20Mintable`.\n *\n * *For a detailed writeup see our guide [How to implement supply\n * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an `Approval` event is emitted on calls to `transferFrom`.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See `IERC20.approve`.\n */\ncontract ERC20 is IERC20 {\n    using SafeMath for uint256;\n\n    mapping (address => uint256) private _balances;\n\n    mapping (address => mapping (address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    /**\n     * @dev See `IERC20.totalSupply`.\n     */\n    function totalSupply() public view returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See `IERC20.balanceOf`.\n     */\n    function balanceOf(address account) public view returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See `IERC20.transfer`.\n     *\n     * Requirements:\n     *\n     * - `recipient` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address recipient, uint256 amount) public returns (bool) {\n        _transfer(msg.sender, recipient, amount);\n        return true;\n    }\n\n    /**\n     * @dev See `IERC20.allowance`.\n     */\n    function allowance(address owner, address spender) public view returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See `IERC20.approve`.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public returns (bool) {\n        _approve(msg.sender, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See `IERC20.transferFrom`.\n     *\n     * Emits an `Approval` event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of `ERC20`;\n     *\n     * Requirements:\n     * - `sender` and `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `value`.\n     * - the caller must have allowance for `sender`'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {\n        _transfer(sender, recipient, amount);\n        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to `approve` that can be used as a mitigation for\n     * problems described in `IERC20.approve`.\n     *\n     * Emits an `Approval` event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {\n        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to `approve` that can be used as a mitigation for\n     * problems described in `IERC20.approve`.\n     *\n     * Emits an `Approval` event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {\n        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));\n        return true;\n    }\n\n    /**\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\n     *\n     * This is internal function is equivalent to `transfer`, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a `Transfer` event.\n     *\n     * Requirements:\n     *\n     * - `sender` cannot be the zero address.\n     * - `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     */\n    function _transfer(address sender, address recipient, uint256 amount) internal {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _balances[sender] = _balances[sender].sub(amount);\n        _balances[recipient] = _balances[recipient].add(amount);\n        emit Transfer(sender, recipient, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a `Transfer` event with `from` set to the zero address.\n     *\n     * Requirements\n     *\n     * - `to` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _totalSupply = _totalSupply.add(amount);\n        _balances[account] = _balances[account].add(amount);\n        emit Transfer(address(0), account, amount);\n    }\n\n     /**\n     * @dev Destoys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a `Transfer` event with `to` set to the zero address.\n     *\n     * Requirements\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 value) internal {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _totalSupply = _totalSupply.sub(value);\n        _balances[account] = _balances[account].sub(value);\n        emit Transfer(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.\n     *\n     * This is internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an `Approval` event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = value;\n        emit Approval(owner, spender, value);\n    }\n\n    /**\n     * @dev Destoys `amount` tokens from `account`.`amount` is then deducted\n     * from the caller's allowance.\n     *\n     * See `_burn` and `_approve`.\n     */\n    function _burnFrom(address account, uint256 amount) internal {\n        _burn(account, amount);\n        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/roles/MinterRole.sol": {
      "content": "pragma solidity ^0.5.0;\n\nimport \"../Roles.sol\";\n\ncontract MinterRole {\n    using Roles for Roles.Role;\n\n    event MinterAdded(address indexed account);\n    event MinterRemoved(address indexed account);\n\n    Roles.Role private _minters;\n\n    constructor () internal {\n        _addMinter(msg.sender);\n    }\n\n    modifier onlyMinter() {\n        require(isMinter(msg.sender), \"MinterRole: caller does not have the Minter role\");\n        _;\n    }\n\n    function isMinter(address account) public view returns (bool) {\n        return _minters.has(account);\n    }\n\n    function addMinter(address account) public onlyMinter {\n        _addMinter(account);\n    }\n\n    function renounceMinter() public {\n        _removeMinter(msg.sender);\n    }\n\n    function _addMinter(address account) internal {\n        _minters.add(account);\n        emit MinterAdded(account);\n    }\n\n    function _removeMinter(address account) internal {\n        _minters.remove(account);\n        emit MinterRemoved(account);\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/Roles.sol": {
      "content": "pragma solidity ^0.5.0;\n\n/**\n * @title Roles\n * @dev Library for managing addresses assigned to a Role.\n */\nlibrary Roles {\n    struct Role {\n        mapping (address => bool) bearer;\n    }\n\n    /**\n     * @dev Give an account access to this role.\n     */\n    function add(Role storage role, address account) internal {\n        require(!has(role, account), \"Roles: account already has role\");\n        role.bearer[account] = true;\n    }\n\n    /**\n     * @dev Remove an account's access to this role.\n     */\n    function remove(Role storage role, address account) internal {\n        require(has(role, account), \"Roles: account does not have role\");\n        role.bearer[account] = false;\n    }\n\n    /**\n     * @dev Check if an account has this role.\n     * @return bool\n     */\n    function has(Role storage role, address account) internal view returns (bool) {\n        require(account != address(0), \"Roles: account is the zero address\");\n        return role.bearer[account];\n    }\n}\n"
    },
    "contracts/5/PaidFantastic12Factory.sol": {
      "content": "pragma solidity 0.5.16;\n\nimport \"./Fantastic12.sol\";\nimport \"@openzeppelin/contracts/ownership/Ownable.sol\";\nimport \"./EIP1167/CloneFactory.sol\";\n\ncontract PaidFantastic12Factory is Ownable, CloneFactory {\n  address public constant DAI_ADDR = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n\n  uint256 public priceInDAI = 0;\n  address public beneficiary = 0x332D87209f7c8296389C307eAe170c2440830A47;\n  address public template;\n\n  event CreateSquad(address indexed summoner, address squad);\n\n  constructor(address _template) public {\n    template = _template;\n  }\n\n  function createSquad(address _summoner, uint256 _withdrawLimit, uint256 _consensusThreshold)\n    public\n    returns (Fantastic12 _squad)\n  {\n    // Transfer fee from msg.sender\n    if (priceInDAI > 0) {\n      IERC20 dai = IERC20(DAI_ADDR);\n      require(dai.transferFrom(msg.sender, address(this), priceInDAI), \"DAI transferFrom failed\");\n      require(dai.transfer(beneficiary, priceInDAI), \"DAI transfer failed\");\n    }\n\n    // Create squad\n    _squad = Fantastic12(_toPayableAddr(createClone(template)));\n    _squad.init(_summoner, DAI_ADDR, _withdrawLimit, _consensusThreshold);\n    emit CreateSquad(_summoner, address(_squad));\n  }\n\n  function setPrice(uint256 _newPrice) public onlyOwner {\n    priceInDAI = _newPrice;\n  }\n\n  function setBeneficiary(address _newBeneficiary) public onlyOwner {\n    require(_newBeneficiary != address(0), \"0 address\");\n    beneficiary = _newBeneficiary;\n  }\n\n  function _toPayableAddr(address _addr) internal pure returns (address payable) {\n    return address(uint160(_addr));\n  }\n}"
    },
    "@openzeppelin/contracts/ownership/Ownable.sol": {
      "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be aplied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor () internal {\n        _owner = msg.sender;\n        emit OwnershipTransferred(address(0), _owner);\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(isOwner(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Returns true if the caller is the current owner.\n     */\n    function isOwner() public view returns (bool) {\n        return msg.sender == _owner;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * > Note: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public onlyOwner {\n        emit OwnershipTransferred(_owner, address(0));\n        _owner = address(0);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public onlyOwner {\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     */\n    function _transferOwnership(address newOwner) internal {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        emit OwnershipTransferred(_owner, newOwner);\n        _owner = newOwner;\n    }\n}\n"
    },
    "contracts/5/standard_bounties/v2/BountiesMetaTxRelayer.sol": {
      "content": "pragma solidity 0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"./StandardBounties.sol\";\n\ncontract BountiesMetaTxRelayer {\n\n  // This contract serves as a relayer for meta txns being sent to the Bounties contract\n\n  StandardBounties public bountiesContract;\n  mapping(address => uint) public replayNonce;\n\n\n  constructor(address _contract) public {\n    bountiesContract = StandardBounties(_contract);\n  }\n\n  function metaIssueBounty(\n    bytes memory signature,\n    address payable [] memory _issuers,\n    address [] memory _approvers,\n    string memory _data,\n    uint _deadline,\n    address _token,\n    uint _tokenVersion,\n    uint _nonce)\n    public\n    returns (uint)\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaIssueBounty\",\n                                                  _issuers,\n                                                  _approvers,\n                                                  _data,\n                                                  _deadline,\n                                                  _token,\n                                                  _tokenVersion,\n                                                  _nonce));\n    address signer = getSigner(metaHash, signature);\n\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n    return bountiesContract.issueBounty(address(uint160(signer)),\n                                         _issuers,\n                                         _approvers,\n                                         _data,\n                                         _deadline,\n                                         _token,\n                                         _tokenVersion);\n  }\n\n  function metaIssueAndContribute(\n    bytes memory signature,\n    address payable [] memory _issuers,\n    address [] memory _approvers,\n    string memory _data,\n    uint _deadline,\n    address _token,\n    uint _tokenVersion,\n    uint _depositAmount,\n    uint _nonce)\n    public\n    payable\n    returns (uint)\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaIssueAndContribute\",\n                                                  _issuers,\n                                                  _approvers,\n                                                  _data,\n                                                  _deadline,\n                                                  _token,\n                                                  _tokenVersion,\n                                                  _depositAmount,\n                                                  _nonce));\n    address signer = getSigner(metaHash, signature);\n\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    if (msg.value > 0){\n      return bountiesContract.issueAndContribute.value(msg.value)(address(uint160(signer)),\n                                                 _issuers,\n                                                 _approvers,\n                                                 _data,\n                                                 _deadline,\n                                                 _token,\n                                                 _tokenVersion,\n                                                 _depositAmount);\n    } else {\n      return bountiesContract.issueAndContribute(address(uint160(signer)),\n                                                 _issuers,\n                                                 _approvers,\n                                                 _data,\n                                                 _deadline,\n                                                 _token,\n                                                 _tokenVersion,\n                                                 _depositAmount);\n    }\n\n  }\n\n  function metaContribute(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _amount,\n    uint _nonce)\n    public\n    payable\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaContribute\",\n                                                  _bountyId,\n                                                  _amount,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    if (msg.value > 0){\n      bountiesContract.contribute.value(msg.value)(address(uint160(signer)), _bountyId, _amount);\n    } else {\n      bountiesContract.contribute(address(uint160(signer)), _bountyId, _amount);\n    }\n  }\n\n\n  function metaRefundContribution(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _contributionId,\n    uint _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaRefundContribution\",\n                                                  _bountyId,\n                                                  _contributionId,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.refundContribution(signer, _bountyId, _contributionId);\n  }\n\n  function metaRefundMyContributions(\n    bytes memory _signature,\n    uint _bountyId,\n    uint [] memory _contributionIds,\n    uint _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaRefundMyContributions\",\n                                                  _bountyId,\n                                                  _contributionIds,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.refundMyContributions(signer, _bountyId, _contributionIds);\n  }\n\n  function metaRefundContributions(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    uint [] memory _contributionIds,\n    uint _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaRefundContributions\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _contributionIds,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.refundContributions(signer, _bountyId, _issuerId, _contributionIds);\n  }\n\n  function metaDrainBounty(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    uint [] memory _amounts,\n    uint _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaDrainBounty\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _amounts,\n                                                  _nonce));\n    address payable signer = address(uint160(getSigner(metaHash, _signature)));\n\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.drainBounty(signer, _bountyId, _issuerId, _amounts);\n  }\n\n  function metaPerformAction(\n    bytes memory _signature,\n    uint _bountyId,\n    string memory _data,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaPerformAction\",\n                                                  _bountyId,\n                                                  _data,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.performAction(signer, _bountyId, _data);\n  }\n\n  function metaFulfillBounty(\n    bytes memory _signature,\n    uint _bountyId,\n    address payable [] memory  _fulfillers,\n    string memory _data,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaFulfillBounty\",\n                                                  _bountyId,\n                                                  _fulfillers,\n                                                  _data,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.fulfillBounty(signer, _bountyId, _fulfillers, _data);\n  }\n\n  function metaUpdateFulfillment(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _fulfillmentId,\n    address payable [] memory  _fulfillers,\n    string memory _data,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaUpdateFulfillment\",\n                                                  _bountyId,\n                                                  _fulfillmentId,\n                                                  _fulfillers,\n                                                  _data,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.updateFulfillment(signer, _bountyId, _fulfillmentId, _fulfillers, _data);\n  }\n\n  function metaAcceptFulfillment(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _fulfillmentId,\n    uint _approverId,\n    uint [] memory _tokenAmounts,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaAcceptFulfillment\",\n                                                  _bountyId,\n                                                  _fulfillmentId,\n                                                  _approverId,\n                                                  _tokenAmounts,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.acceptFulfillment(signer,\n                       _bountyId,\n                       _fulfillmentId,\n                       _approverId,\n                       _tokenAmounts);\n  }\n\n  function metaFulfillAndAccept(\n    bytes memory _signature,\n    uint _bountyId,\n    address payable [] memory _fulfillers,\n    string memory _data,\n    uint _approverId,\n    uint [] memory _tokenAmounts,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaFulfillAndAccept\",\n                                                  _bountyId,\n                                                  _fulfillers,\n                                                  _data,\n                                                  _approverId,\n                                                  _tokenAmounts,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.fulfillAndAccept(signer,\n                      _bountyId,\n                      _fulfillers,\n                      _data,\n                      _approverId,\n                      _tokenAmounts);\n  }\n\n  function metaChangeBounty(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _issuers,\n    address payable [] memory _approvers,\n    string memory _data,\n    uint _deadline,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaChangeBounty\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _issuers,\n                                                  _approvers,\n                                                  _data,\n                                                  _deadline,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.changeBounty(signer,\n                  _bountyId,\n                  _issuerId,\n                  _issuers,\n                  _approvers,\n                  _data,\n                  _deadline);\n  }\n\n  function metaChangeIssuer(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    uint _issuerIdToChange,\n    address payable _newIssuer,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaChangeIssuer\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _issuerIdToChange,\n                                                  _newIssuer,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.changeIssuer(signer,\n                  _bountyId,\n                  _issuerId,\n                  _issuerIdToChange,\n                  _newIssuer);\n  }\n\n  function metaChangeApprover(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    uint _approverId,\n    address payable _approver,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaChangeApprover\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _approverId,\n                                                  _approver,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.changeApprover(signer,\n                  _bountyId,\n                  _issuerId,\n                  _approverId,\n                  _approver);\n  }\n\n  function metaChangeData(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    string memory _data,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaChangeData\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _data,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.changeData(signer,\n                _bountyId,\n                _issuerId,\n                _data);\n  }\n\n  function metaChangeDeadline(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    uint  _deadline,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaChangeDeadline\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _deadline,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.changeDeadline(signer,\n                    _bountyId,\n                    _issuerId,\n                    _deadline);\n  }\n\n  function metaAddIssuers(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _issuers,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaAddIssuers\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _issuers,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.addIssuers(signer,\n                _bountyId,\n                _issuerId,\n                _issuers);\n  }\n\n  function metaReplaceIssuers(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _issuers,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaReplaceIssuers\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _issuers,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.replaceIssuers(signer,\n                    _bountyId,\n                    _issuerId,\n                    _issuers);\n  }\n\n  function metaAddApprovers(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _approvers,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaAddApprovers\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _approvers,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.addIssuers(signer,\n                _bountyId,\n                _issuerId,\n                _approvers);\n  }\n\n  function metaReplaceApprovers(\n    bytes memory _signature,\n    uint _bountyId,\n    uint _issuerId,\n    address payable [] memory _approvers,\n    uint256 _nonce)\n    public\n    {\n    bytes32 metaHash = keccak256(abi.encode(address(this),\n                                                  \"metaReplaceApprovers\",\n                                                  _bountyId,\n                                                  _issuerId,\n                                                  _approvers,\n                                                  _nonce));\n    address signer = getSigner(metaHash, _signature);\n    //make sure signer doesn't come back as 0x0\n    require(signer != address(0));\n    require(_nonce == replayNonce[signer]);\n\n    //increase the nonce to prevent replay attacks\n    replayNonce[signer]++;\n\n    bountiesContract.replaceIssuers(signer,\n                    _bountyId,\n                    _issuerId,\n                    _approvers);\n  }\n\n  function getSigner(\n    bytes32 _hash,\n    bytes memory _signature)\n    internal\n    pure\n    returns (address)\n  {\n    bytes32 r;\n    bytes32 s;\n    uint8 v;\n    if (_signature.length != 65) {\n      return address(0);\n    }\n    assembly {\n      r := mload(add(_signature, 32))\n      s := mload(add(_signature, 64))\n      v := byte(0, mload(add(_signature, 96)))\n    }\n    if (v < 27) {\n      v += 27;\n    }\n    if (v != 27 && v != 28) {\n      return address(0);\n    } else {\n      return ecrecover(keccak256(\n        abi.encode(\"\\x19Ethereum Signed Message:\\n32\", _hash)\n      ), v, r, s);\n    }\n  }\n}\n"
    }
  },
  "settings": {
    "metadata": {
      "useLiteralContent": true
    },
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "abi"
        ]
      }
    }
  }
}}