{
  "language": "Solidity",
  "sources": {
    "src/tokens/WrappedWeiToken.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n  mapping(address => bool) private consumers;\n\n  // events\n\n  /**\n   * @dev Emitted when the new consumer is added\n   * @param consumer consumer address\n   */\n  event ConsumerAdded(\n    address consumer\n  );\n\n  /**\n   * @dev Emitted when the existing consumer is removed\n   * @param consumer consumer address\n   */\n  event ConsumerRemoved(\n    address consumer\n  );\n\n  /**\n   * @dev Public constructor\n   */\n  constructor()\n    public\n    Initializable()\n  {\n    name = \"Wrapped Wei\";\n    symbol = \"WWEI\";\n  }\n\n  /**\n   * @notice Receive fallback\n   */\n  receive()\n    external\n    payable\n  {\n    _mint(_getSender(), msg.value);\n  }\n\n  // external functions\n\n  /**\n   * @notice Initializes `WrappedWeiToken` contract\n   * @param consumers_ array of consumers addresses\n   * @param gateway_ `Gateway` contract address\n   */\n  function initialize(\n    address[] calldata consumers_,\n    address gateway_\n  )\n    external\n    onlyInitializer\n  {\n    if (consumers_.length != 0) {\n      uint consumersLen = consumers_.length;\n      for (uint i = 0; i < consumersLen; i++) {\n        _addConsumer(consumers_[i]);\n      }\n    }\n\n    _initializeGatewayRecipient(gateway_);\n  }\n\n  /**\n   * @notice Starts consuming\n   * @dev Add caller as a consumer\n   */\n  function startConsuming()\n    external\n  {\n    _addConsumer(_getSender());\n  }\n\n  /**\n   * @notice Stops consuming\n   * @dev Remove caller from consumers\n   */\n  function stopConsuming()\n    external\n  {\n    address consumer = _getSender();\n\n    require(\n      consumers[consumer],\n      \"WrappedWeiToken: consumer doesn't exist\"\n    );\n\n    consumers[consumer] = false;\n\n    emit ConsumerRemoved(consumer);\n  }\n\n  /**\n   * @notice Deposits `msg.value` to address\n   * @param to to address\n   */\n  function depositTo(\n    address to\n  )\n    external\n    payable\n  {\n    _mint(to, msg.value);\n  }\n\n  /**\n   * @notice Withdraws\n   * @param value value to withdraw\n   */\n  function withdraw(\n    uint256 value\n  )\n    external\n  {\n    _withdraw(_getSender(), _getSender(), value);\n  }\n\n  /**\n   * @notice Withdraws to address\n   * @param to to address\n   * @param value value to withdraw\n   */\n  function withdrawTo(\n    address to,\n    uint256 value\n  )\n    external\n  {\n    _withdraw(_getSender(), to, value);\n  }\n\n  /**\n   * @notice Withdraws all\n   */\n  function withdrawAll()\n    external\n  {\n    address sender = _getSender();\n\n    _withdraw(sender, sender, balances[sender]);\n  }\n\n  /**\n   * @notice Withdraws all to address\n   * @param to to address\n   */\n  function withdrawAllTo(\n    address to\n  )\n    external\n  {\n    address sender = _getSender();\n\n    _withdraw(sender, to, balances[sender]);\n  }\n\n  // external functions (views)\n\n  /**\n   * @notice Checks if consumer exists\n   * @param consumer consumer address\n   * @return true if consumer exists\n   */\n  function isConsumer(\n    address consumer\n  )\n    external\n    view\n    returns (bool)\n  {\n    return consumers[consumer];\n  }\n\n  // internal functions\n\n  function _transfer(\n    address from,\n    address to,\n    uint256 value\n  )\n    override\n    internal\n  {\n    if (consumers[to]) {\n      _withdraw(from, to, value);\n    } else {\n      super._transfer(from, to, value);\n    }\n  }\n\n  // internal functions (views)\n\n  function _getSender()\n    override\n    internal\n    view\n    returns (address)\n  {\n    return _getContextAccount();\n  }\n\n  // private functions\n\n  function _addConsumer(\n    address consumer\n  )\n    private\n  {\n    require(\n      !consumers[consumer],\n      \"WrappedWeiToken: consumer already exists\"\n    );\n\n    consumers[consumer] = true;\n\n    emit ConsumerAdded(consumer);\n  }\n\n  function _withdraw(\n    address from,\n    address to,\n    uint256 value\n  )\n    private\n  {\n    _burn(from, value);\n\n    require(\n      // solhint-disable-next-line check-send-result\n      payable(to).send(value),\n      \"WrappedWeiToken: transaction reverted\"\n    );\n  }\n}\n"
    },
    "src/common/lifecycle/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\ncontract Initializable {\n  address private initializer;\n\n  // events\n\n  /**\n   * @dev Emitted after `onlyInitializer`\n   * @param initializer initializer address\n   */\n  event Initialized(\n    address initializer\n  );\n\n  // modifiers\n\n  /**\n   * @dev Throws if tx.origin is not the initializer\n   */\n  modifier onlyInitializer() {\n    require(\n      // solhint-disable-next-line avoid-tx-origin\n      tx.origin == initializer,\n      \"Initializable: tx.origin is not the initializer\"\n    );\n\n    /// @dev removes initializer\n    initializer = address(0);\n\n    _;\n\n    emit Initialized(\n      // solhint-disable-next-line avoid-tx-origin\n      tx.origin\n    );\n  }\n\n  /**\n   * @dev Internal constructor\n   */\n  constructor()\n    internal\n  {\n    // solhint-disable-next-line avoid-tx-origin\n    initializer = tx.origin;\n  }\n\n   // external functions (views)\n\n  /**\n   * @notice Check if contract is initialized\n   * @return true when contract is initialized\n   */\n  function isInitialized()\n    external\n    view\n    returns (bool)\n  {\n    return initializer == address(0);\n  }\n}\n"
    },
    "src/common/token/ERC20Token.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n  using SafeMathLib for uint256;\n\n  string public name;\n  string public symbol;\n  uint8 public decimals;\n  uint256 public totalSupply;\n\n  mapping(address => uint256) internal balances;\n  mapping(address => mapping(address => uint256)) internal allowances;\n\n  // events\n\n  event Transfer(\n    address indexed from,\n    address indexed to,\n    uint256 value\n  );\n\n  event Approval(\n    address indexed owner,\n    address indexed spender,\n    uint256 value\n  );\n\n  /**\n   * @dev internal constructor\n   */\n  constructor() internal {}\n\n  // external functions\n\n  function transfer(\n    address to,\n    uint256 value\n  )\n    external\n    returns (bool)\n  {\n    _transfer(_getSender(), to, value);\n\n    return true;\n  }\n\n  function transferFrom(\n    address from,\n    address to,\n    uint256 value\n  )\n    virtual\n    external\n    returns (bool)\n  {\n    address sender = _getSender();\n\n    _transfer(from, to, value);\n    _approve(from, sender, allowances[from][sender].sub(value));\n\n    return true;\n  }\n\n  function approve(\n    address spender,\n    uint256 value\n  )\n    virtual\n    external\n    returns (bool)\n  {\n    _approve(_getSender(), spender, value);\n\n    return true;\n  }\n\n  // external functions (views)\n\n  function balanceOf(\n    address owner\n  )\n    virtual\n    external\n    view\n    returns (uint256)\n  {\n    return balances[owner];\n  }\n\n  function allowance(\n    address owner,\n    address spender\n  )\n    virtual\n    external\n    view\n    returns (uint256)\n  {\n    return allowances[owner][spender];\n  }\n\n  // internal functions\n\n  function _transfer(\n    address from,\n    address to,\n    uint256 value\n  )\n    virtual\n    internal\n  {\n    require(\n      from != address(0),\n      \"ERC20Token: cannot transfer from 0x0 address\"\n    );\n    require(\n      to != address(0),\n      \"ERC20Token: cannot transfer to 0x0 address\"\n    );\n\n    balances[from] = balances[from].sub(value);\n    balances[to] = balances[to].add(value);\n\n    emit Transfer(from, to, value);\n  }\n\n  function _approve(\n    address owner,\n    address spender,\n    uint256 value\n  )\n    virtual\n    internal\n  {\n    require(\n      owner != address(0),\n      \"ERC20Token: cannot approve from 0x0 address\"\n    );\n    require(\n      spender != address(0),\n      \"ERC20Token: cannot approve to 0x0 address\"\n    );\n\n    allowances[owner][spender] = value;\n\n    emit Approval(owner, spender, value);\n  }\n\n  function _mint(\n    address owner,\n    uint256 value\n  )\n    virtual\n    internal\n  {\n    require(\n      owner != address(0),\n      \"ERC20Token: cannot mint to 0x0 address\"\n    );\n    require(\n      value > 0,\n      \"ERC20Token: cannot mint 0 value\"\n    );\n\n    balances[owner] = balances[owner].add(value);\n    totalSupply = totalSupply.add(value);\n\n    emit Transfer(address(0), owner, value);\n  }\n\n  function _burn(\n    address owner,\n    uint256 value\n  )\n    virtual\n    internal\n  {\n    require(\n      owner != address(0),\n      \"ERC20Token: cannot burn from 0x0 address\"\n    );\n\n    balances[owner] = balances[owner].sub(\n      value,\n      \"ERC20Token: burn value exceeds balance\"\n    );\n\n    totalSupply = totalSupply.sub(value);\n\n    emit Transfer(owner, address(0), value);\n  }\n\n  // internal functions (views)\n\n  function _getSender()\n    virtual\n    internal\n    view\n    returns (address)\n  {\n    return msg.sender;\n  }\n}\n"
    },
    "src/gateway/GatewayRecipient.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\ncontract GatewayRecipient {\n  using BytesLib for bytes;\n\n  address public gateway;\n\n  /**\n   * @dev internal constructor\n   */\n  constructor() internal {}\n\n  // internal functions\n\n  /**\n   * @notice Initializes `GatewayRecipient` contract\n   * @param gateway_ `Gateway` contract address\n   */\n  function _initializeGatewayRecipient(\n    address gateway_\n  )\n    internal\n  {\n    gateway = gateway_;\n  }\n\n  // internal functions (views)\n\n  /**\n   * @notice Gets gateway context account\n   * @return context account address\n   */\n  function _getContextAccount()\n    internal\n    view\n    returns (address)\n  {\n    return _getContextAddress(40);\n  }\n\n  /**\n   * @notice Gets gateway context sender\n   * @return context sender address\n   */\n  function _getContextSender()\n    internal\n    view\n    returns (address)\n  {\n    return _getContextAddress(20);\n  }\n\n  /**\n   * @notice Gets gateway context data\n   * @return context data\n   */\n  function _getContextData()\n    internal\n    view\n    returns (bytes calldata)\n  {\n    bytes calldata result;\n\n    if (_isGatewaySender()) {\n      result = msg.data[:msg.data.length - 40];\n    } else {\n      result = msg.data;\n    }\n\n    return result;\n  }\n\n  // private functions (views)\n\n  function _getContextAddress(\n    uint256 offset\n  )\n    private\n    view\n    returns (address)\n  {\n    address result = address(0);\n\n    if (_isGatewaySender()) {\n      uint from = msg.data.length - offset;\n      result = bytes(msg.data[from:from + 20]).toAddress();\n    } else {\n      result = msg.sender;\n    }\n\n    return result;\n  }\n\n  function _isGatewaySender()\n    private\n    view\n    returns (bool)\n  {\n    bool result;\n\n    if (msg.sender == gateway) {\n      require(\n        msg.data.length >= 44,\n        \"GatewayRecipient: invalid msg.data\"\n      );\n\n      result = true;\n    }\n\n    return result;\n  }\n}\n"
    },
    "src/common/libs/SafeMathLib.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n  function add(uint256 a, uint256 b) internal pure returns (uint256) {\n    uint256 c = a + b;\n\n    require(c >= a, \"SafeMathLib: addition overflow\");\n\n    return c;\n  }\n\n  function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n    return sub(a, b, \"SafeMathLib: subtraction overflow\");\n  }\n\n  function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n    require(b <= a, errorMessage);\n\n    return a - b;\n  }\n\n  function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n    if (a == 0) {\n      return 0;\n    }\n\n    uint256 c = a * b;\n\n    require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n    return c;\n  }\n\n  function div(uint256 a, uint256 b) internal pure returns (uint256) {\n    return div(a, b, \"SafeMathLib: division by zero\");\n  }\n\n  function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n    require(b > 0, errorMessage);\n\n    return a / b;\n  }\n\n  function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n    return mod(a, b, \"SafeMathLib: modulo by zero\");\n  }\n\n  function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n    require(b != 0, errorMessage);\n\n    return a % b;\n  }\n}\n"
    },
    "src/common/libs/BytesLib.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\nlibrary BytesLib {\n  /**\n   * @notice Converts bytes to address\n   * @param data data\n   * @return address\n   */\n  function toAddress(\n    bytes memory data\n  )\n    internal\n    pure\n    returns (address)\n  {\n    address result;\n\n    require(\n      data.length == 20,\n      \"BytesLib: invalid data length\"\n    );\n\n    // solhint-disable-next-line no-inline-assembly\n    assembly {\n      result := div(mload(add(data, 0x20)), 0x1000000000000000000000000)\n    }\n\n    return result;\n  }\n}\n"
    }
  },
  "settings": {
    "evmVersion": "istanbul",
    "metadata": {
      "bytecodeHash": "none",
      "useLiteralContent": true
    },
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    }
  }
}