{
  "address": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163",
  "abi": [
    {
      "inputs": [],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "bytes",
          "name": "batch",
          "type": "bytes"
        },
        {
          "indexed": false,
          "internalType": "bool",
          "name": "succeeded",
          "type": "bool"
        }
      ],
      "name": "BatchDelegated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "initializer",
          "type": "address"
        }
      ],
      "name": "Initialized",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "chainId",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "nonce",
          "type": "uint256"
        },
        {
          "internalType": "address[]",
          "name": "to",
          "type": "address[]"
        },
        {
          "internalType": "bytes[]",
          "name": "data",
          "type": "bytes[]"
        },
        {
          "internalType": "bytes",
          "name": "senderSignature",
          "type": "bytes"
        }
      ],
      "name": "delegateBatch",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "nonce",
          "type": "uint256"
        },
        {
          "internalType": "address[]",
          "name": "to",
          "type": "address[]"
        },
        {
          "internalType": "bytes[]",
          "name": "data",
          "type": "bytes[]"
        },
        {
          "internalType": "bytes",
          "name": "senderSignature",
          "type": "bytes"
        }
      ],
      "name": "delegateBatchWithGasPrice",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes[]",
          "name": "batches",
          "type": "bytes[]"
        },
        {
          "internalType": "bool",
          "name": "revertOnFailure",
          "type": "bool"
        }
      ],
      "name": "delegateBatches",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "externalAccountRegistry",
      "outputs": [
        {
          "internalType": "contract ExternalAccountRegistry",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "getAccountNextNonce",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "account",
              "type": "address"
            },
            {
              "internalType": "uint256",
              "name": "nonce",
              "type": "uint256"
            },
            {
              "internalType": "address[]",
              "name": "to",
              "type": "address[]"
            },
            {
              "internalType": "bytes[]",
              "name": "data",
              "type": "bytes[]"
            }
          ],
          "internalType": "struct Gateway.DelegatedBatch",
          "name": "delegatedBatch",
          "type": "tuple"
        }
      ],
      "name": "hashDelegatedBatch",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "account",
              "type": "address"
            },
            {
              "internalType": "uint256",
              "name": "nonce",
              "type": "uint256"
            },
            {
              "internalType": "address[]",
              "name": "to",
              "type": "address[]"
            },
            {
              "internalType": "bytes[]",
              "name": "data",
              "type": "bytes[]"
            },
            {
              "internalType": "uint256",
              "name": "gasPrice",
              "type": "uint256"
            }
          ],
          "internalType": "struct Gateway.DelegatedBatchWithGasPrice",
          "name": "delegatedBatch",
          "type": "tuple"
        }
      ],
      "name": "hashDelegatedBatchWithGasPrice",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract ExternalAccountRegistry",
          "name": "externalAccountRegistry_",
          "type": "address"
        },
        {
          "internalType": "contract PersonalAccountRegistry",
          "name": "personalAccountRegistry_",
          "type": "address"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "isInitialized",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "personalAccountRegistry",
      "outputs": [
        {
          "internalType": "contract PersonalAccountRegistry",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "to",
          "type": "address[]"
        },
        {
          "internalType": "bytes[]",
          "name": "data",
          "type": "bytes[]"
        }
      ],
      "name": "sendBatch",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "address[]",
          "name": "to",
          "type": "address[]"
        },
        {
          "internalType": "bytes[]",
          "name": "data",
          "type": "bytes[]"
        }
      ],
      "name": "sendBatchFromAccount",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0xca8335c747f3f57fee8054d7aa416715a392bdc13be312ae45632c899b68e6ca",
  "receipt": {
    "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C",
    "from": "0x53fE9288897e254698175740aa359E19E26c10af",
    "contractAddress": null,
    "transactionIndex": 1,
    "gasUsed": "2080112",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xee92aefcd2d07a6bc7a343b6d97ad8cc660164554b5e023fc8f2f5a9e80ac6e9",
    "transactionHash": "0xca8335c747f3f57fee8054d7aa416715a392bdc13be312ae45632c899b68e6ca",
    "logs": [],
    "blockNumber": 7138976,
    "cumulativeGasUsed": "4947099",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae",
  "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"batch\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"succeeded\",\"type\":\"bool\"}],\"name\":\"BatchDelegated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"}],\"name\":\"delegateBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"}],\"name\":\"delegateBatchWithGasPrice\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"batches\",\"type\":\"bytes[]\"},{\"internalType\":\"bool\",\"name\":\"revertOnFailure\",\"type\":\"bool\"}],\"name\":\"delegateBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"externalAccountRegistry\",\"outputs\":[{\"internalType\":\"contract ExternalAccountRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountNextNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"internalType\":\"struct Gateway.DelegatedBatch\",\"name\":\"delegatedBatch\",\"type\":\"tuple\"}],\"name\":\"hashDelegatedBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct Gateway.DelegatedBatchWithGasPrice\",\"name\":\"delegatedBatch\",\"type\":\"tuple\"}],\"name\":\"hashDelegatedBatchWithGasPrice\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ExternalAccountRegistry\",\"name\":\"externalAccountRegistry_\",\"type\":\"address\"},{\"internalType\":\"contract PersonalAccountRegistry\",\"name\":\"personalAccountRegistry_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"personalAccountRegistry\",\"outputs\":[{\"internalType\":\"contract PersonalAccountRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatchFromAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\",\"events\":{\"BatchDelegated(address,bytes,bool)\":{\"details\":\"Emitted when the single batch is delegated\",\"params\":{\"batch\":\"batch\",\"sender\":\"sender address\",\"succeeded\":\"if succeeded\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"},\"delegateBatch(address,uint256,address[],bytes[],bytes)\":{\"details\":\"Use `hashDelegatedBatch` to create sender message payload. `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"nonce\":\"next account nonce\",\"senderSignature\":\"sender signature\",\"to\":\"array of batch recipients contracts\"}},\"delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)\":{\"details\":\"Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice) `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"nonce\":\"next account nonce\",\"senderSignature\":\"sender signature\",\"to\":\"array of batch recipients contracts\"}},\"delegateBatches(bytes[],bool)\":{\"details\":\"It will revert when all batches fail\",\"params\":{\"batches\":\"array of batches\",\"revertOnFailure\":\"reverts on any error\"}},\"getAccountNextNonce(address)\":{\"params\":{\"account\":\"account address\"},\"returns\":{\"_0\":\"next nonce\"}},\"hashDelegatedBatch((address,uint256,address[],bytes[]))\":{\"params\":{\"delegatedBatch\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))\":{\"params\":{\"delegatedBatch\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"initialize(address,address)\":{\"params\":{\"externalAccountRegistry_\":\"`ExternalAccountRegistry` contract address\",\"personalAccountRegistry_\":\"`PersonalAccountRegistry` contract address\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"sendBatch(address[],bytes[])\":{\"details\":\"`GatewayRecipient` context api: `_getContextAccount` will return `msg.sender` `_getContextSender` will return `msg.sender`\",\"params\":{\"data\":\"array of batch data\",\"to\":\"array of batch recipients contracts\"}},\"sendBatchFromAccount(address,address[],bytes[])\":{\"details\":\"`GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return `msg.sender`\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"to\":\"array of batch recipients contracts\"}}},\"title\":\"Gateway\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"delegateBatch(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account\"},\"delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account (with gas price)\"},\"delegateBatches(bytes[],bool)\":{\"notice\":\"Delegates multiple batches\"},\"getAccountNextNonce(address)\":{\"notice\":\"Gets next account nonce\"},\"hashDelegatedBatch((address,uint256,address[],bytes[]))\":{\"notice\":\"Hashes `DelegatedBatch` message payload\"},\"hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))\":{\"notice\":\"Hashes `DelegatedBatchWithGasPrice` message payload\"},\"initialize(address,address)\":{\"notice\":\"Initializes `Gateway` contract\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"sendBatch(address[],bytes[])\":{\"notice\":\"Sends batch\"},\"sendBatchFromAccount(address,address[],bytes[])\":{\"notice\":\"Sends batch from the account\"}},\"notice\":\"GSN replacement\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/gateway/Gateway.sol\":\"Gateway\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/common/access/Controlled.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\n/**\\n * @title Controlled\\n *\\n * @dev Contract module which provides an access control mechanism.\\n * It ensures there is only one controlling account of the smart contract\\n * and grants that account exclusive access to specific functions.\\n *\\n * The controller account will be the one that deploys the contract.\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract Controlled {\\n  /**\\n   * @return controller account address\\n   */\\n  address public controller;\\n\\n  // modifiers\\n\\n  /**\\n   * @dev Throws if msg.sender is not the controller\\n   */\\n  modifier onlyController() {\\n    require(\\n      msg.sender == controller,\\n      \\\"Controlled: msg.sender is not the controller\\\"\\n    );\\n\\n    _;\\n  }\\n\\n  /**\\n   * @dev Internal constructor\\n   */\\n  constructor()\\n    internal\\n  {\\n    controller = msg.sender;\\n  }\\n}\\n\",\"keccak256\":\"0xdf03a0b7ec644da9925c5c1b6c8a86bb1cc1b9c5018bb265a1a4c5044b877af3\",\"license\":\"MIT\"},\"src/common/access/Guarded.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../libs/ECDSALib.sol\\\";\\n\\n\\n/**\\n * @title Guarded\\n *\\n * @dev Contract module which provides a guardian-type control mechanism.\\n * It allows key accounts to have guardians and restricts specific methods to be accessible by guardians only.\\n *\\n * Each guardian account can remove other guardians\\n *\\n * Use `_initializeGuarded` to initialize the contract\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract Guarded {\\n  using ECDSALib for bytes32;\\n\\n  mapping(address => bool) private guardians;\\n\\n  // events\\n\\n  /**\\n   * @dev Emitted when a new guardian is added\\n   * @param sender sender address\\n   * @param guardian guardian address\\n   */\\n  event GuardianAdded(\\n    address sender,\\n    address guardian\\n  );\\n\\n  /**\\n   * @dev Emitted when the existing guardian is removed\\n   * @param sender sender address\\n   * @param guardian guardian address\\n   */\\n  event GuardianRemoved(\\n    address sender,\\n    address guardian\\n  );\\n\\n  // modifiers\\n\\n  /**\\n   * @dev Throws if tx.origin is not a guardian account\\n   */\\n  modifier onlyGuardian() {\\n    require(\\n      // solhint-disable-next-line avoid-tx-origin\\n      guardians[tx.origin],\\n      \\\"Guarded: tx.origin is not the guardian\\\"\\n    );\\n\\n    _;\\n  }\\n\\n  /**\\n   * @dev Internal constructor\\n   */\\n  constructor() internal {}\\n\\n  // external functions\\n\\n  /**\\n   * @notice Adds a new guardian\\n   * @param guardian guardian address\\n   */\\n  function addGuardian(\\n    address guardian\\n  )\\n    external\\n    onlyGuardian\\n  {\\n    _addGuardian(guardian);\\n  }\\n\\n  /**\\n   * @notice Removes the existing guardian\\n   * @param guardian guardian address\\n   */\\n  function removeGuardian(\\n    address guardian\\n  )\\n    external\\n    onlyGuardian\\n  {\\n    require(\\n      // solhint-disable-next-line avoid-tx-origin\\n      tx.origin != guardian,\\n      \\\"Guarded: cannot remove self\\\"\\n    );\\n\\n    require(\\n      guardians[guardian],\\n      \\\"Guarded: guardian doesn't exist\\\"\\n    );\\n\\n    guardians[guardian] = false;\\n\\n    emit GuardianRemoved(\\n      // solhint-disable-next-line avoid-tx-origin\\n      tx.origin,\\n      guardian\\n    );\\n  }\\n\\n  // external functions (views)\\n\\n  /**\\n   * @notice Check if guardian exists\\n   * @param guardian guardian address\\n   * @return true when guardian exists\\n   */\\n  function isGuardian(\\n    address guardian\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return guardians[guardian];\\n  }\\n\\n  /**\\n   * @notice Verifies guardian signature\\n   * @param messageHash message hash\\n   * @param signature signature\\n   * @return true on correct guardian signature\\n   */\\n  function verifyGuardianSignature(\\n    bytes32 messageHash,\\n    bytes calldata signature\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return _verifyGuardianSignature(\\n      messageHash,\\n      signature\\n    );\\n  }\\n\\n  // internal functions\\n\\n  /**\\n   * @notice Initializes `Guarded` contract\\n   * @dev If `guardians_` array is empty `tx.origin` is added as guardian account\\n   * @param guardians_ array of guardians addresses\\n   */\\n  function _initializeGuarded(\\n    address[] memory guardians_\\n  )\\n    internal\\n  {\\n    if (guardians_.length == 0) {\\n      // solhint-disable-next-line avoid-tx-origin\\n      _addGuardian(tx.origin);\\n    } else {\\n      uint guardiansLen = guardians_.length;\\n      for (uint i = 0; i < guardiansLen; i++) {\\n        _addGuardian(guardians_[i]);\\n      }\\n    }\\n  }\\n\\n\\n  // internal functions (views)\\n\\n  function _verifyGuardianSignature(\\n    bytes32 messageHash,\\n    bytes memory signature\\n  )\\n    internal\\n    view\\n    returns (bool)\\n  {\\n    address guardian = messageHash.recoverAddress(signature);\\n\\n    return guardians[guardian];\\n  }\\n\\n  // private functions\\n\\n  function _addGuardian(\\n    address guardian\\n  )\\n    private\\n  {\\n    require(\\n      guardian != address(0),\\n      \\\"Guarded: cannot add 0x0 guardian\\\"\\n    );\\n\\n    require(\\n      !guardians[guardian],\\n      \\\"Guarded: guardian already exists\\\"\\n    );\\n\\n    guardians[guardian] = true;\\n\\n    emit GuardianAdded(\\n      // solhint-disable-next-line avoid-tx-origin\\n      tx.origin,\\n      guardian\\n    );\\n  }\\n}\\n\",\"keccak256\":\"0x4a5f5670041362e87ea267d81c55fc3edc1a78e81f6f17524b13267f91f31458\",\"license\":\"MIT\"},\"src/common/account/Account.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../access/Controlled.sol\\\";\\nimport \\\"./AccountBase.sol\\\";\\n\\n\\n/**\\n * @title Account\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract Account is Controlled, AccountBase {\\n  address public implementation;\\n\\n  /**\\n   * @dev Public constructor\\n   * @param registry_ account registry address\\n   * @param implementation_ account implementation address\\n   */\\n  constructor(\\n    address registry_,\\n    address implementation_\\n  )\\n    public\\n    Controlled()\\n  {\\n    registry = registry_;\\n    implementation = implementation_;\\n  }\\n\\n  // external functions\\n\\n  /**\\n   * @notice Payable receive\\n   */\\n  receive()\\n    external\\n    payable\\n  {\\n    //\\n  }\\n\\n  /**\\n   * @notice Fallback\\n   */\\n  // solhint-disable-next-line payable-fallback\\n  fallback()\\n    external\\n  {\\n    if (msg.data.length != 0) {\\n      address implementation_ = implementation;\\n\\n      // solhint-disable-next-line no-inline-assembly\\n      assembly {\\n        let calldedatasize := calldatasize()\\n\\n        calldatacopy(0, 0, calldedatasize)\\n\\n        let result := delegatecall(gas(), implementation_, 0, calldedatasize, 0, 0)\\n        let returneddatasize := returndatasize()\\n\\n        returndatacopy(0, 0, returneddatasize)\\n\\n        switch result\\n        case 0 { revert(0, returneddatasize) }\\n        default { return(0, returneddatasize) }\\n      }\\n    }\\n  }\\n\\n  /**\\n   * @notice Sets implementation\\n   * @param implementation_ implementation address\\n   */\\n  function setImplementation(\\n    address implementation_\\n  )\\n    external\\n    onlyController\\n  {\\n    implementation = implementation_;\\n  }\\n\\n  /**\\n   * @notice Executes transaction\\n   * @param to to address\\n   * @param value value\\n   * @param data data\\n   * @return transaction result\\n   */\\n  function executeTransaction(\\n    address to,\\n    uint256 value,\\n    bytes calldata data\\n  )\\n    external\\n    onlyController\\n    returns (bytes memory)\\n  {\\n    bytes memory result;\\n    bool succeeded;\\n\\n    // solhint-disable-next-line avoid-call-value, avoid-low-level-calls\\n    (succeeded, result) = payable(to).call{value: value}(data);\\n\\n    require(\\n      succeeded,\\n      \\\"Account: transaction reverted\\\"\\n    );\\n\\n    return result;\\n  }\\n}\\n\",\"keccak256\":\"0xe516c999a02a65ee99487d398d0c12589500680a9ca08c852540fb9473d70a26\",\"license\":\"MIT\"},\"src/common/account/AccountBase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\n/**\\n * @title Account base\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract AccountBase {\\n  address public registry;\\n}\\n\",\"keccak256\":\"0xcadf29e389f8db823e14f3f92808fd135f07b0135eb4dcf29b89c85941b39862\",\"license\":\"MIT\"},\"src/common/account/AccountController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"./Account.sol\\\";\\n\\n\\n/**\\n * @title Account controller\\n *\\n * @dev Contract module which provides Account deployment mechanism\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract AccountController {\\n  address public accountRegistry;\\n  address public accountImplementation;\\n\\n  // events\\n\\n  /**\\n   * @dev Emitted when the account registry is updated\\n   * @param accountRegistry account registry address\\n   */\\n  event AccountRegistryUpdated(\\n    address accountRegistry\\n  );\\n\\n  /**\\n   * @dev Emitted when the account implementation is updated\\n   * @param accountImplementation account implementation address\\n   */\\n  event AccountImplementationUpdated(\\n    address accountImplementation\\n  );\\n\\n  /**\\n   * @dev Emitted when the account is deployed\\n   * @param account account address\\n   * @param accountImplementation account implementation address\\n   */\\n  event AccountDeployed(\\n    address account,\\n    address accountImplementation\\n  );\\n\\n  /**\\n   * @dev Emitted when the account is upgraded\\n   * @param account account address\\n   * @param accountImplementation account implementation address\\n   */\\n  event AccountUpgraded(\\n    address account,\\n    address accountImplementation\\n  );\\n\\n  /**\\n   * @dev Emitted when the transaction is executed\\n   * @param account account address\\n   * @param to to address\\n   * @param value value\\n   * @param data data\\n   * @param response response\\n   */\\n  event AccountTransactionExecuted(\\n    address account,\\n    address to,\\n    uint256 value,\\n    bytes data,\\n    bytes response\\n  );\\n\\n  /**\\n   * @dev Internal constructor\\n   */\\n  constructor() internal {}\\n\\n  // internal functions\\n\\n  /**\\n   * @notice Initializes `AccountController` contract\\n   * @param accountRegistry_ account registry address\\n   * @param accountImplementation_ account implementation address\\n   */\\n  function _initializeAccountController(\\n    address accountRegistry_,\\n    address accountImplementation_\\n  )\\n    internal\\n  {\\n    _setAccountRegistry(accountRegistry_, false);\\n    _setAccountImplementation(accountImplementation_, false);\\n  }\\n\\n  /**\\n   * @notice Sets account registry\\n   * @param accountRegistry_ account registry address\\n   * @param emitEvent it will emit event when flag is set to true\\n   */\\n  function _setAccountRegistry(\\n    address accountRegistry_,\\n    bool emitEvent\\n  )\\n    internal\\n  {\\n    require(\\n      accountRegistry_ != address(0),\\n      \\\"AccountController: cannot set account registry to 0x0\\\"\\n    );\\n\\n    accountRegistry = accountRegistry_;\\n\\n    if (emitEvent) {\\n      emit AccountRegistryUpdated(accountRegistry);\\n    }\\n  }\\n\\n  /**\\n   * @notice Sets account implementation\\n   * @param accountImplementation_ account implementation address\\n   * @param emitEvent it will emit event when flag is set to true\\n   */\\n  function _setAccountImplementation(\\n    address accountImplementation_,\\n    bool emitEvent\\n  )\\n    internal\\n  {\\n    require(\\n      accountImplementation_ != address(0),\\n      \\\"AccountController: cannot set account Implementation to 0x0\\\"\\n    );\\n\\n    accountImplementation = accountImplementation_;\\n\\n    if (emitEvent) {\\n      emit AccountImplementationUpdated(accountImplementation);\\n    }\\n  }\\n\\n  /**\\n   * @notice Deploys account\\n   * @param salt CREATE2 salt\\n   * @param emitEvent it will emit event when flag is set to true\\n   * @return account address\\n   */\\n  function _deployAccount(\\n    bytes32 salt,\\n    bool emitEvent\\n  )\\n    internal\\n    returns (address)\\n  {\\n    address account = address(new Account{salt: salt}(\\n      accountRegistry,\\n      accountImplementation\\n    ));\\n\\n    if (emitEvent) {\\n      emit AccountDeployed(\\n        account,\\n        accountImplementation\\n      );\\n    }\\n\\n    return account;\\n  }\\n\\n  /**\\n   * @notice Upgrades account\\n   * @param account account address\\n   * @param emitEvent it will emit event when flag is set to true\\n   */\\n  function _upgradeAccount(\\n    address account,\\n    bool emitEvent\\n  )\\n    internal\\n  {\\n    require(\\n      Account(payable(account)).implementation() != accountImplementation,\\n      \\\"AccountController: account already upgraded\\\"\\n    );\\n\\n    Account(payable(account)).setImplementation(accountImplementation);\\n\\n    if (emitEvent) {\\n      emit AccountUpgraded(\\n        account,\\n        accountImplementation\\n      );\\n    }\\n  }\\n\\n  /**\\n   * @notice Executes transaction from the account\\n   * @param account account address\\n   * @param to to address\\n   * @param value value\\n   * @param data data\\n   * @param emitEvent it will emit event when flag is set to true\\n   * @return transaction result\\n   */\\n  function _executeAccountTransaction(\\n    address account,\\n    address to,\\n    uint256 value,\\n    bytes memory data,\\n    bool emitEvent\\n  )\\n    internal\\n    returns (bytes memory)\\n  {\\n    require(\\n      to != address(0),\\n      \\\"AccountController: cannot send to 0x0\\\"\\n    );\\n\\n    require(\\n      to != address(this),\\n      \\\"AccountController: cannot send to controller\\\"\\n    );\\n\\n    require(\\n      to != account,\\n      \\\"AccountController: cannot send to self\\\"\\n    );\\n\\n    bytes memory response = Account(payable(account)).executeTransaction(\\n      to,\\n      value,\\n      data\\n    );\\n\\n    if (emitEvent) {\\n      emit AccountTransactionExecuted(\\n        account,\\n        to,\\n        value,\\n        data,\\n        response\\n      );\\n    }\\n\\n    return response;\\n  }\\n\\n  // internal functions (views)\\n\\n  /**\\n   * @notice Computes account CREATE2 address\\n   * @param salt CREATE2 salt\\n   * @return account address\\n   */\\n  function _computeAccountAddress(\\n    bytes32 salt\\n  )\\n    internal\\n    view\\n    returns (address)\\n  {\\n    bytes memory creationCode = abi.encodePacked(\\n      type(Account).creationCode,\\n      bytes12(0),\\n      accountRegistry,\\n      bytes12(0),\\n      accountImplementation\\n    );\\n\\n    bytes32 data = keccak256(\\n      abi.encodePacked(\\n        bytes1(0xff),\\n        address(this),\\n        salt,\\n        keccak256(creationCode)\\n      )\\n    );\\n\\n    return address(uint160(uint256(data)));\\n  }\\n}\\n\",\"keccak256\":\"0xe161f1f4f6ea5d3a9810f7c93764d55e473abe1054e6aa68fde791be7d70a26c\",\"license\":\"MIT\"},\"src/common/account/AccountRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"./Account.sol\\\";\\n\\n\\n/**\\n * @title Account registry\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\nabstract contract AccountRegistry {\\n  /**\\n   * @notice Verifies account signature\\n   * @param account account address\\n   * @param messageHash message hash\\n   * @param signature signature\\n   * @return true if valid\\n   */\\n  function isValidAccountSignature(\\n    address account,\\n    bytes32 messageHash,\\n    bytes calldata signature\\n  )\\n    virtual\\n    external\\n    view\\n    returns (bool);\\n\\n  /**\\n   * @notice Verifies account signature\\n   * @param account account address\\n   * @param message message\\n   * @param signature signature\\n   * @return true if valid\\n   */\\n  function isValidAccountSignature(\\n    address account,\\n    bytes calldata message,\\n    bytes calldata signature\\n  )\\n    virtual\\n    external\\n    view\\n    returns (bool);\\n}\\n\",\"keccak256\":\"0x2d40245721f5f74219e5cf88713246dbe8b6d5404e941125d3e850b1f127ec34\",\"license\":\"MIT\"},\"src/common/libs/BlockLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\n/**\\n * @title Block library\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\nlibrary BlockLib {\\n  struct BlockRelated {\\n    bool added;\\n    uint256 removedAtBlockNumber;\\n  }\\n\\n  /**\\n   * @notice Verifies self struct at current block\\n   * @param self self struct\\n   * @return true on correct self struct\\n   */\\n  function verifyAtCurrentBlock(\\n    BlockRelated memory self\\n  )\\n    internal\\n    view\\n    returns (bool)\\n  {\\n    return verifyAtBlock(self, block.number);\\n  }\\n\\n  /**\\n   * @notice Verifies self struct at any block\\n   * @param self self struct\\n   * @return true on correct self struct\\n   */\\n  function verifyAtAnyBlock(\\n    BlockRelated memory self\\n  )\\n    internal\\n    pure\\n    returns (bool)\\n  {\\n    return verifyAtBlock(self, 0);\\n  }\\n\\n  /**\\n   * @notice Verifies self struct at specific block\\n   * @param self self struct\\n   * @param blockNumber block number to verify\\n   * @return true on correct self struct\\n   */\\n  function verifyAtBlock(\\n    BlockRelated memory self,\\n    uint256 blockNumber\\n  )\\n    internal\\n    pure\\n    returns (bool)\\n  {\\n    bool result = false;\\n\\n    if (self.added) {\\n      if (self.removedAtBlockNumber == 0) {\\n        result = true;\\n      } else if (blockNumber == 0) {\\n        result = true;\\n      } else {\\n        result = self.removedAtBlockNumber > blockNumber;\\n      }\\n    }\\n\\n    return result;\\n  }\\n}\\n\",\"keccak256\":\"0x9205536bc211f86d1113118a44dddfa7a9b9772a918cf4b1575c982a05472587\",\"license\":\"MIT\"},\"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\\u0142aw G\\u0142ogowski <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\",\"keccak256\":\"0x64c84964ea91bfb1f2d859eea6c57fe5b4a6f269951a4adf5f58d306c54c7f76\",\"license\":\"MIT\"},\"src/common/libs/ECDSAExtendedLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"./StringsLib.sol\\\";\\n\\n\\n/**\\n * @title ECDSA extended library\\n */\\nlibrary ECDSAExtendedLib {\\n  using StringsLib for uint;\\n\\n  function toEthereumSignedMessageHash(\\n    bytes memory message\\n  )\\n    internal\\n    pure\\n    returns (bytes32)\\n  {\\n    return keccak256(abi.encodePacked(\\n      \\\"\\\\x19Ethereum Signed Message:\\\\n\\\",\\n      message.length.toString(),\\n      abi.encodePacked(message)\\n    ));\\n  }\\n}\\n\",\"keccak256\":\"0x83e6056caaba892d91de45324f4d2702ac01695fab2d34c86895d7d288547ba3\",\"license\":\"MIT\"},\"src/common/libs/ECDSALib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\n/**\\n * @title ECDSA library\\n *\\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/cryptography/ECDSA.sol#L26\\n */\\nlibrary ECDSALib {\\n  function recoverAddress(\\n    bytes32 messageHash,\\n    bytes memory signature\\n  )\\n    internal\\n    pure\\n    returns (address)\\n  {\\n    address result = address(0);\\n\\n    if (signature.length == 65) {\\n      bytes32 r;\\n      bytes32 s;\\n      uint8 v;\\n\\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      if (v < 27) {\\n        v += 27;\\n      }\\n\\n      if (v == 27 || v == 28) {\\n        result = ecrecover(messageHash, v, r, s);\\n      }\\n    }\\n\\n    return result;\\n  }\\n\\n  function toEthereumSignedMessageHash(\\n    bytes32 messageHash\\n  )\\n    internal\\n    pure\\n    returns (bytes32)\\n  {\\n    return keccak256(abi.encodePacked(\\n      \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n      messageHash\\n    ));\\n  }\\n}\\n\",\"keccak256\":\"0x3b1460d688302eb595268c2af147ab532f29dbced66520e013f48d498eed3cec\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x6089f354ca754d9c5dd9e800ee5ed86717dbf8f9af470604e0be691ac57c0107\",\"license\":\"MIT\"},\"src/common/libs/StringsLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\n/**\\n * @title Strings library\\n *\\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/utils/Strings.sol#L12\\n */\\nlibrary StringsLib {\\n  function toString(\\n    uint256 value\\n  )\\n    internal\\n    pure\\n    returns (string memory)\\n  {\\n    if (value == 0) {\\n      return \\\"0\\\";\\n    }\\n\\n    uint256 temp = value;\\n    uint256 digits;\\n\\n    while (temp != 0) {\\n      digits++;\\n      temp /= 10;\\n    }\\n\\n    bytes memory buffer = new bytes(digits);\\n    uint256 index = digits - 1;\\n    temp = value;\\n\\n    while (temp != 0) {\\n      buffer[index--] = byte(uint8(48 + temp % 10));\\n      temp /= 10;\\n    }\\n\\n    return string(buffer);\\n  }\\n}\\n\",\"keccak256\":\"0x4110150d0c921fd31db34ca33672de8e81c3ae467076149a3a546f804d1f58dd\",\"license\":\"MIT\"},\"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\\u0142aw G\\u0142ogowski <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\",\"keccak256\":\"0x3d47b2864dde5bde245917f7ac416a9e9715cdf1d226897e49838eb3186ee067\",\"license\":\"MIT\"},\"src/common/signature/SignatureValidator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../libs/ECDSALib.sol\\\";\\n\\n/**\\n * @title Signature validator\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract SignatureValidator {\\n  using ECDSALib for bytes32;\\n\\n  uint256 public chainId;\\n\\n  /**\\n   * @dev internal constructor\\n   */\\n  constructor() internal {\\n    uint256 chainId_;\\n\\n    // solhint-disable-next-line no-inline-assembly\\n    assembly {\\n      chainId_ := chainid()\\n    }\\n\\n    chainId = chainId_;\\n  }\\n\\n  // internal functions\\n\\n  function _hashMessagePayload(\\n    bytes32 messagePrefix,\\n    bytes memory messagePayload\\n  )\\n    internal\\n    view\\n    returns (bytes32)\\n  {\\n    return keccak256(abi.encodePacked(\\n      chainId,\\n      address(this),\\n      messagePrefix,\\n      messagePayload\\n    )).toEthereumSignedMessageHash();\\n  }\\n}\\n\",\"keccak256\":\"0xc1168f7ccb74aea67089941dc5e4c1d1c4aa766afca47a90c0b017b8445b8acf\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x6f2b0bd08da549c6c1f5ceee85766832d587dde62c56bebc3a14bd9ea407e03d\",\"license\":\"MIT\"},\"src/external/ExternalAccountRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../common/libs/BlockLib.sol\\\";\\n\\n\\n/**\\n * @title External account registry\\n *\\n * @notice Global registry for keys and external (outside of the platform) contract based wallets\\n *\\n * @dev An account can call the registry to add (`addAccountOwner`) or remove (`removeAccountOwner`) its own owners.\\n * When the owner has been added, information about that fact will live in the registry forever.\\n * Removing an owner only affects the future blocks (until the owner is re-added).\\n *\\n * Given the fact, there is no way to sign the data using a contract based wallet,\\n * we created a registry to store signed by the key wallet proofs.\\n * ERC-1271 allows removing a signer after the signature was created. Thus store the signature for the later use\\n * doesn't guarantee the signer is still has access to that smart account.\\n * Because of that, the ERC1271's `isValidSignature()` cannot be used in e.g. `PaymentRegistry`.*\\n *\\n * An account can call the registry to add (`addAccountProof`) or remove (`removeAccountProof`) proof hash.\\n * When the proof has been added, information about that fact will live in the registry forever.\\n * Removing a proof only affects the future blocks (until the proof is re-added).\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract ExternalAccountRegistry {\\n  using BlockLib for BlockLib.BlockRelated;\\n\\n  struct Account {\\n    mapping(address => BlockLib.BlockRelated) owners;\\n    mapping(bytes32 => BlockLib.BlockRelated) proofs;\\n  }\\n\\n  mapping(address => Account) private accounts;\\n\\n  // events\\n\\n  /**\\n   * @dev Emitted when the new owner is added\\n   * @param account account address\\n   * @param owner owner address\\n   */\\n  event AccountOwnerAdded(\\n    address account,\\n    address owner\\n  );\\n\\n  /**\\n   * @dev Emitted when the existing owner is removed\\n   * @param account account address\\n   * @param owner owner address\\n   */\\n  event AccountOwnerRemoved(\\n    address account,\\n    address owner\\n  );\\n\\n  /**\\n   * @dev Emitted when the new proof is added\\n   * @param account account address\\n   * @param hash proof hash\\n   */\\n  event AccountProofAdded(\\n    address account,\\n    bytes32 hash\\n  );\\n\\n  /**\\n   * @dev Emitted when the existing proof is removed\\n   * @param account account address\\n   * @param hash proof hash\\n   */\\n  event AccountProofRemoved(\\n    address account,\\n    bytes32 hash\\n  );\\n\\n  // external functions\\n\\n  /**\\n   * @notice Adds a new account owner\\n   * @param owner owner address\\n   */\\n  function addAccountOwner(\\n    address owner\\n  )\\n    external\\n  {\\n    require(\\n      owner != address(0),\\n      \\\"ExternalAccountRegistry: cannot add 0x0 owner\\\"\\n    );\\n\\n    require(\\n      !accounts[msg.sender].owners[owner].verifyAtCurrentBlock(),\\n      \\\"ExternalAccountRegistry: owner already exists\\\"\\n    );\\n\\n    accounts[msg.sender].owners[owner].added = true;\\n    accounts[msg.sender].owners[owner].removedAtBlockNumber = 0;\\n\\n    emit AccountOwnerAdded(\\n      msg.sender,\\n      owner\\n    );\\n  }\\n\\n  /**\\n   * @notice Removes existing account owner\\n   * @param owner owner address\\n   */\\n  function removeAccountOwner(\\n    address owner\\n  )\\n    external\\n  {\\n    require(\\n      accounts[msg.sender].owners[owner].verifyAtCurrentBlock(),\\n      \\\"ExternalAccountRegistry: owner doesn't exist\\\"\\n    );\\n\\n    accounts[msg.sender].owners[owner].removedAtBlockNumber = block.number;\\n\\n    emit AccountOwnerRemoved(\\n      msg.sender,\\n      owner\\n    );\\n  }\\n\\n  /**\\n   * @notice Adds a new account proof\\n   * @param hash proof hash\\n   */\\n  function addAccountProof(\\n    bytes32 hash\\n  )\\n    external\\n  {\\n    require(\\n      !accounts[msg.sender].proofs[hash].verifyAtCurrentBlock(),\\n      \\\"ExternalAccountRegistry: proof already exists\\\"\\n    );\\n\\n    accounts[msg.sender].proofs[hash].added = true;\\n    accounts[msg.sender].proofs[hash].removedAtBlockNumber = 0;\\n\\n    emit AccountProofAdded(\\n      msg.sender,\\n      hash\\n    );\\n  }\\n\\n  /**\\n   * @notice Removes existing account proof\\n   * @param hash proof hash\\n   */\\n  function removeAccountProof(\\n    bytes32 hash\\n  )\\n    external\\n  {\\n    require(\\n      accounts[msg.sender].proofs[hash].verifyAtCurrentBlock(),\\n      \\\"ExternalAccountRegistry: proof doesn't exist\\\"\\n    );\\n\\n    accounts[msg.sender].proofs[hash].removedAtBlockNumber = block.number;\\n\\n    emit AccountProofRemoved(\\n      msg.sender,\\n      hash\\n    );\\n  }\\n\\n  // external functions (views)\\n\\n  /**\\n   * @notice Verifies the owner of the account at current block\\n   * @param account account address\\n   * @param owner owner address\\n   * @return true on correct account owner\\n   */\\n  function verifyAccountOwner(\\n    address account,\\n    address owner\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return accounts[account].owners[owner].verifyAtCurrentBlock();\\n  }\\n\\n  /**\\n   * @notice Verifies the owner of the account at specific block\\n   * @param account account address\\n   * @param owner owner address\\n   * @param blockNumber block number to verify\\n   * @return true on correct account owner\\n   */\\n  function verifyAccountOwnerAtBlock(\\n    address account,\\n    address owner,\\n    uint256 blockNumber\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return accounts[account].owners[owner].verifyAtBlock(blockNumber);\\n  }\\n\\n  /**\\n   * @notice Verifies the proof of the account at current block\\n   * @param account account address\\n   * @param hash proof hash\\n   * @return true on correct account proof\\n   */\\n  function verifyAccountProof(\\n    address account,\\n    bytes32 hash\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return accounts[account].proofs[hash].verifyAtCurrentBlock();\\n  }\\n\\n  /**\\n   * @notice Verifies the proof of the account at specific block\\n   * @param account account address\\n   * @param hash proof hash\\n   * @param blockNumber block number to verify\\n   * @return true on correct account proof\\n   */\\n  function verifyAccountProofAtBlock(\\n    address account,\\n    bytes32 hash,\\n    uint256 blockNumber\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return accounts[account].proofs[hash].verifyAtBlock(blockNumber);\\n  }\\n}\\n\",\"keccak256\":\"0x8067b1fae41b73949f8d871a835533cbdd94b9ca3faa93b91f595c37e632ccdb\",\"license\":\"MIT\"},\"src/gateway/Gateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../common/libs/ECDSALib.sol\\\";\\nimport \\\"../common/libs/SafeMathLib.sol\\\";\\nimport \\\"../common/lifecycle/Initializable.sol\\\";\\nimport \\\"../common/signature/SignatureValidator.sol\\\";\\nimport \\\"../external/ExternalAccountRegistry.sol\\\";\\nimport \\\"../personal/PersonalAccountRegistry.sol\\\";\\n\\n\\n/**\\n * @title Gateway\\n *\\n * @notice GSN replacement\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract Gateway is Initializable, SignatureValidator {\\n  using ECDSALib for bytes32;\\n  using SafeMathLib for uint256;\\n\\n  struct DelegatedBatch {\\n    address account;\\n    uint256 nonce;\\n    address[] to;\\n    bytes[] data;\\n  }\\n\\n  struct DelegatedBatchWithGasPrice {\\n    address account;\\n    uint256 nonce;\\n    address[] to;\\n    bytes[] data;\\n    uint256 gasPrice;\\n  }\\n\\n  bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256(\\n    \\\"DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)\\\"\\n  );\\n\\n  bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256(\\n    \\\"DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)\\\"\\n  );\\n\\n  ExternalAccountRegistry public externalAccountRegistry;\\n  PersonalAccountRegistry public personalAccountRegistry;\\n\\n  mapping(address => uint256) private accountNonce;\\n\\n  // events\\n\\n  /**\\n   * @dev Emitted when the single batch is delegated\\n   * @param sender sender address\\n   * @param batch batch\\n   * @param succeeded if succeeded\\n   */\\n  event BatchDelegated(\\n    address sender,\\n    bytes batch,\\n    bool succeeded\\n  );\\n\\n  /**\\n   * @dev Public constructor\\n   */\\n  constructor() public Initializable() SignatureValidator() {}\\n\\n  // external functions\\n\\n  /**\\n   * @notice Initializes `Gateway` contract\\n   * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\\n   * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\\n   */\\n  function initialize(\\n    ExternalAccountRegistry externalAccountRegistry_,\\n    PersonalAccountRegistry personalAccountRegistry_\\n  )\\n    external\\n    onlyInitializer\\n  {\\n    externalAccountRegistry = externalAccountRegistry_;\\n    personalAccountRegistry = personalAccountRegistry_;\\n  }\\n\\n  // public functions\\n\\n  /**\\n   * @notice Sends batch\\n   * @dev `GatewayRecipient` context api:\\n   * `_getContextAccount` will return `msg.sender`\\n   * `_getContextSender` will return `msg.sender`\\n   *\\n   * @param to array of batch recipients contracts\\n   * @param data array of batch data\\n   */\\n  function sendBatch(\\n    address[] memory to,\\n    bytes[] memory data\\n  )\\n    public\\n  {\\n    _sendBatch(\\n      msg.sender,\\n      msg.sender,\\n      to,\\n      data\\n    );\\n  }\\n\\n  /**\\n   * @notice Sends batch from the account\\n   * @dev `GatewayRecipient` context api:\\n   * `_getContextAccount` will return `account` arg\\n   * `_getContextSender` will return `msg.sender`\\n   *\\n   * @param account account address\\n   * @param to array of batch recipients contracts\\n   * @param data array of batch data\\n   */\\n  function sendBatchFromAccount(\\n    address account,\\n    address[] memory to,\\n    bytes[] memory data\\n  )\\n    public\\n  {\\n    _sendBatch(\\n      account,\\n      msg.sender,\\n      to,\\n      data\\n    );\\n  }\\n\\n  /**\\n   * @notice Delegates batch from the account\\n   * @dev Use `hashDelegatedBatch` to create sender message payload.\\n   *\\n   * `GatewayRecipient` context api:\\n   * `_getContextAccount` will return `account` arg\\n   * `_getContextSender` will return recovered address from `senderSignature` arg\\n   *\\n   * @param account account address\\n   * @param nonce next account nonce\\n   * @param to array of batch recipients contracts\\n   * @param data array of batch data\\n   * @param senderSignature sender signature\\n   */\\n  function delegateBatch(\\n    address account,\\n    uint256 nonce,\\n    address[] memory to,\\n    bytes[] memory data,\\n    bytes memory senderSignature\\n  )\\n    public\\n  {\\n    require(\\n      nonce > accountNonce[account],\\n      \\\"Gateway: nonce is lower than current account nonce\\\"\\n    );\\n\\n    address sender = _hashDelegatedBatch(\\n      account,\\n      nonce,\\n      to,\\n      data\\n    ).recoverAddress(senderSignature);\\n\\n    accountNonce[account] = nonce;\\n\\n    _sendBatch(\\n      account,\\n      sender,\\n      to,\\n      data\\n    );\\n  }\\n\\n  /**\\n   * @notice Delegates batch from the account (with gas price)\\n   *\\n   * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\\n   *\\n   * `GatewayRecipient` context api:\\n   * `_getContextAccount` will return `account` arg\\n   * `_getContextSender` will return recovered address from `senderSignature` arg\\n   *\\n   * @param account account address\\n   * @param nonce next account nonce\\n   * @param to array of batch recipients contracts\\n   * @param data array of batch data\\n   * @param senderSignature sender signature\\n   */\\n  function delegateBatchWithGasPrice(\\n    address account,\\n    uint256 nonce,\\n    address[] memory to,\\n    bytes[] memory data,\\n    bytes memory senderSignature\\n  )\\n    public\\n  {\\n    require(\\n      nonce > accountNonce[account],\\n      \\\"Gateway: nonce is lower than current account nonce\\\"\\n    );\\n\\n    address sender = _hashDelegatedBatchWithGasPrice(\\n      account,\\n      nonce,\\n      to,\\n      data,\\n      tx.gasprice\\n    ).recoverAddress(senderSignature);\\n\\n    accountNonce[account] = nonce;\\n\\n    _sendBatch(\\n      account,\\n      sender,\\n      to,\\n      data\\n    );\\n  }\\n\\n  /**\\n   * @notice Delegates multiple batches\\n   * @dev It will revert when all batches fail\\n   * @param batches array of batches\\n   * @param revertOnFailure reverts on any error\\n   */\\n  function delegateBatches(\\n    bytes[] memory batches,\\n    bool revertOnFailure\\n  )\\n    public\\n  {\\n    require(\\n      batches.length > 0,\\n      \\\"Gateway: cannot delegate empty batches\\\"\\n    );\\n\\n    bool anySucceeded;\\n\\n    for (uint256 i = 0; i < batches.length; i++) {\\n      // solhint-disable-next-line avoid-low-level-calls\\n      (bool succeeded,) = address(this).call(batches[i]);\\n\\n      if (revertOnFailure) {\\n        require(\\n          succeeded,\\n          \\\"Gateway: batch reverted\\\"\\n        );\\n      } else if (succeeded && !anySucceeded) {\\n        anySucceeded = true;\\n      }\\n\\n      emit BatchDelegated(\\n        msg.sender,\\n        batches[i],\\n        succeeded\\n      );\\n    }\\n\\n    if (!anySucceeded) {\\n      revert(\\\"Gateway: all batches reverted\\\");\\n    }\\n  }\\n\\n  // public functions (views)\\n\\n  /**\\n   * @notice Hashes `DelegatedBatch` message payload\\n   * @param delegatedBatch struct\\n   * @return hash\\n   */\\n  function hashDelegatedBatch(\\n    DelegatedBatch memory delegatedBatch\\n  )\\n    public\\n    view\\n    returns (bytes32)\\n  {\\n    return _hashDelegatedBatch(\\n      delegatedBatch.account,\\n      delegatedBatch.nonce,\\n      delegatedBatch.to,\\n      delegatedBatch.data\\n    );\\n  }\\n\\n  /**\\n   * @notice Hashes `DelegatedBatchWithGasPrice` message payload\\n   * @param delegatedBatch struct\\n   * @return hash\\n   */\\n  function hashDelegatedBatchWithGasPrice(\\n    DelegatedBatchWithGasPrice memory delegatedBatch\\n  )\\n    public\\n    view\\n    returns (bytes32)\\n  {\\n    return _hashDelegatedBatchWithGasPrice(\\n      delegatedBatch.account,\\n      delegatedBatch.nonce,\\n      delegatedBatch.to,\\n      delegatedBatch.data,\\n      delegatedBatch.gasPrice\\n    );\\n  }\\n\\n  // external functions (views)\\n\\n  /**\\n   * @notice Gets next account nonce\\n   * @param account account address\\n   * @return next nonce\\n   */\\n  function getAccountNextNonce(\\n    address account\\n  )\\n    external\\n    view\\n    returns (uint256)\\n  {\\n    return accountNonce[account].add(1);\\n  }\\n\\n  // private functions\\n\\n  function _sendBatch(\\n    address account,\\n    address sender,\\n    address[] memory to,\\n    bytes[] memory data\\n  )\\n    private\\n  {\\n    require(\\n      account != address(0),\\n      \\\"Gateway: cannot send from 0x0 account\\\"\\n    );\\n    require(\\n      to.length > 0,\\n      \\\"Gateway: cannot send empty batch\\\"\\n    );\\n    require(\\n      data.length == to.length,\\n      \\\"Gateway: invalid batch\\\"\\n    );\\n\\n    if (account != sender) {\\n      require(\\n        personalAccountRegistry.verifyAccountOwner(account, sender) ||\\n        externalAccountRegistry.verifyAccountOwner(account, sender),\\n        \\\"Gateway: sender is not the account owner\\\"\\n      );\\n    }\\n\\n    bool succeeded;\\n\\n    for (uint256 i = 0; i < data.length; i++) {\\n      require(\\n        to[i] != address(0),\\n        \\\"Gateway: cannot send to 0x0\\\"\\n      );\\n\\n      // solhint-disable-next-line avoid-low-level-calls\\n      (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender));\\n\\n      require(\\n        succeeded,\\n        \\\"Gateway: batch transaction reverted\\\"\\n      );\\n    }\\n  }\\n\\n  // private functions (views)\\n\\n  function _hashDelegatedBatch(\\n    address account,\\n    uint256 nonce,\\n    address[] memory to,\\n    bytes[] memory data\\n  )\\n    private\\n    view\\n    returns (bytes32)\\n  {\\n    return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked(\\n      account,\\n      nonce,\\n      to,\\n      _concatBytes(data)\\n    ));\\n  }\\n\\n  function _hashDelegatedBatchWithGasPrice(\\n    address account,\\n    uint256 nonce,\\n    address[] memory to,\\n    bytes[] memory data,\\n    uint256 gasPrice\\n  )\\n    private\\n    view\\n    returns (bytes32)\\n  {\\n    return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked(\\n      account,\\n      nonce,\\n      to,\\n      _concatBytes(data),\\n      gasPrice\\n    ));\\n  }\\n\\n// private functions (pure)\\n\\n  function _concatBytes(bytes[] memory data)\\n    private\\n    pure\\n    returns (bytes memory)\\n  {\\n    bytes memory result;\\n    uint dataLen = data.length;\\n\\n    for (uint i = 0 ; i < dataLen ; i++) {\\n      result = abi.encodePacked(result, data[i]);\\n    }\\n\\n    return result;\\n  }\\n}\\n\",\"keccak256\":\"0x666f10ebf96aef0a37607852871a6e1d816a271558b1dce43dda74fc73274ae4\",\"license\":\"MIT\"},\"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\\u0142aw G\\u0142ogowski <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\",\"keccak256\":\"0xe3fd29479d748d67360c61a9cbaafc66eaca25f476e59a45e842472bcf5233fc\",\"license\":\"MIT\"},\"src/personal/PersonalAccountRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../common/access/Guarded.sol\\\";\\nimport \\\"../common/account/AccountController.sol\\\";\\nimport \\\"../common/account/AccountRegistry.sol\\\";\\nimport \\\"../common/libs/BlockLib.sol\\\";\\nimport \\\"../common/libs/ECDSALib.sol\\\";\\nimport \\\"../common/libs/ECDSAExtendedLib.sol\\\";\\nimport \\\"../common/libs/SafeMathLib.sol\\\";\\nimport \\\"../common/lifecycle/Initializable.sol\\\";\\nimport \\\"../common/token/ERC20Token.sol\\\";\\nimport \\\"../gateway/GatewayRecipient.sol\\\";\\n\\n\\n/**\\n * @title Personal account registry\\n *\\n * @notice A registry for personal (controlled by owners) accounts\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski <stan@pillarproject.io>\\n */\\ncontract PersonalAccountRegistry is Guarded, AccountController, AccountRegistry, Initializable, GatewayRecipient {\\n  using BlockLib for BlockLib.BlockRelated;\\n  using SafeMathLib for uint256;\\n  using ECDSALib for bytes32;\\n  using ECDSAExtendedLib for bytes;\\n\\n  struct Account {\\n    bool deployed;\\n    bytes32 salt;\\n    mapping(address => BlockLib.BlockRelated) owners;\\n  }\\n\\n  mapping(address => Account) private accounts;\\n\\n  // events\\n\\n  /**\\n   * @dev Emitted when the new owner is added\\n   * @param account account address\\n   * @param owner owner address\\n   */\\n  event AccountOwnerAdded(\\n    address account,\\n    address owner\\n  );\\n\\n  /**\\n   * @dev Emitted when the existing owner is removed\\n   * @param account account address\\n   * @param owner owner address\\n   */\\n  event AccountOwnerRemoved(\\n    address account,\\n    address owner\\n  );\\n\\n  /**\\n   * @dev Emitted when the call is refunded\\n   * @param account account address\\n   * @param beneficiary beneficiary address\\n   * @param token token address\\n   * @param value value\\n   */\\n  event AccountCallRefunded(\\n    address account,\\n    address beneficiary,\\n    address token,\\n    uint256 value\\n  );\\n\\n  /**\\n   * @dev Public constructor\\n   */\\n  constructor() public Initializable() {}\\n\\n  // external functions\\n\\n  /**\\n   * @notice Initializes `PersonalAccountRegistry` contract\\n   * @param guardians_ array of guardians addresses\\n   * @param accountImplementation_ account implementation address\\n   * @param gateway_ `Gateway` contract address\\n   */\\n  function initialize(\\n    address[] calldata guardians_,\\n    address accountImplementation_,\\n    address gateway_\\n  )\\n    external\\n    onlyInitializer\\n  {\\n    // Guarded\\n    _initializeGuarded(guardians_);\\n\\n    // AccountController\\n    _initializeAccountController(address(this), accountImplementation_);\\n\\n    // GatewayRecipient\\n    _initializeGatewayRecipient(gateway_);\\n  }\\n\\n  /**\\n   * @notice Upgrades `PersonalAccountRegistry` contract\\n   * @param accountImplementation_ account implementation address\\n   */\\n  function upgrade(\\n    address accountImplementation_\\n  )\\n    external\\n    onlyGuardian\\n  {\\n    _setAccountImplementation(accountImplementation_, true);\\n  }\\n\\n  /**\\n   * @notice Deploys account\\n   * @param account account address\\n   */\\n  function deployAccount(\\n    address account\\n  )\\n    external\\n  {\\n    _verifySender(account);\\n    _deployAccount(account);\\n  }\\n\\n  /**\\n   * @notice Upgrades account\\n   * @param account account address\\n   */\\n  function upgradeAccount(\\n    address account\\n  )\\n    external\\n  {\\n    _verifySender(account);\\n    _upgradeAccount(account, true);\\n  }\\n\\n  /**\\n   * @notice Adds a new account owner\\n   * @param account account address\\n   * @param owner owner address\\n   */\\n  function addAccountOwner(\\n    address account,\\n    address owner\\n  )\\n    external\\n  {\\n    _verifySender(account);\\n\\n    require(\\n      owner != address(0),\\n      \\\"PersonalAccountRegistry: cannot add 0x0 owner\\\"\\n    );\\n\\n    require(\\n      !accounts[account].owners[owner].verifyAtCurrentBlock(),\\n      \\\"PersonalAccountRegistry: owner already exists\\\"\\n    );\\n\\n    accounts[account].owners[owner].added = true;\\n    accounts[account].owners[owner].removedAtBlockNumber = 0;\\n\\n    emit AccountOwnerAdded(\\n      account,\\n      owner\\n    );\\n  }\\n\\n  /**\\n   * @notice Removes the existing account owner\\n   * @param account account address\\n   * @param owner owner address\\n   */\\n  function removeAccountOwner(\\n    address account,\\n    address owner\\n  )\\n    external\\n  {\\n    address sender = _verifySender(account);\\n\\n    require(\\n      owner != sender,\\n      \\\"PersonalAccountRegistry: cannot remove self\\\"\\n    );\\n\\n    require(\\n      accounts[account].owners[owner].verifyAtCurrentBlock(),\\n      \\\"PersonalAccountRegistry: owner doesn't exist\\\"\\n    );\\n\\n    accounts[account].owners[owner].removedAtBlockNumber = block.number;\\n\\n    emit AccountOwnerRemoved(\\n      account,\\n      owner\\n    );\\n  }\\n\\n  /**\\n   * @notice Executes account transaction\\n   * @dev Deploys an account if not deployed yet\\n   * @param account account address\\n   * @param to to address\\n   * @param value value\\n   * @param data data\\n   */\\n  function executeAccountTransaction(\\n    address account,\\n    address to,\\n    uint256 value,\\n    bytes calldata data\\n  )\\n    external\\n  {\\n    _verifySender(account);\\n\\n    _deployAccount(account);\\n\\n    _executeAccountTransaction(\\n      account,\\n      to,\\n      value,\\n      data,\\n      true\\n    );\\n  }\\n\\n  /**\\n   * @notice Refunds account call\\n   * @dev Deploys an account if not deployed yet\\n   * @param account account address\\n   * @param token token address\\n   * @param value value\\n   */\\n  function refundAccountCall(\\n    address account,\\n    address token,\\n    uint256 value\\n  )\\n    external\\n  {\\n    _verifySender(account);\\n\\n    _deployAccount(account);\\n\\n    /* solhint-disable avoid-tx-origin */\\n\\n    if (token == address(0)) {\\n      _executeAccountTransaction(\\n        account,\\n        tx.origin,\\n        value,\\n        new bytes(0),\\n        false\\n      );\\n    } else {\\n      bytes memory response = _executeAccountTransaction(\\n        account,\\n        token,\\n        0,\\n        abi.encodeWithSelector(\\n          ERC20Token(token).transfer.selector,\\n          tx.origin,\\n          value\\n        ),\\n        false\\n      );\\n\\n      if (response.length > 0) {\\n        require(\\n          abi.decode(response, (bool)),\\n          \\\"PersonalAccountRegistry: ERC20Token transfer reverted\\\"\\n        );\\n      }\\n    }\\n\\n    emit AccountCallRefunded(\\n      account,\\n      tx.origin,\\n      token,\\n      value\\n    );\\n\\n    /* solhint-enable avoid-tx-origin */\\n  }\\n\\n  // external functions (views)\\n\\n  /**\\n   * @notice Computes account address\\n   * @param saltOwner salt owner address\\n   * @return account address\\n   */\\n  function computeAccountAddress(\\n    address saltOwner\\n  )\\n    external\\n    view\\n    returns (address)\\n  {\\n    return _computeAccountAddress(saltOwner);\\n  }\\n\\n  /**\\n   * @notice Checks if account is deployed\\n   * @param account account address\\n   * @return true when account is deployed\\n   */\\n  function isAccountDeployed(\\n    address account\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return accounts[account].deployed;\\n  }\\n\\n  /**\\n   * @notice Verifies the owner of the account at the current block\\n   * @param account account address\\n   * @param owner owner address\\n   * @return true on correct account owner\\n   */\\n  function verifyAccountOwner(\\n    address account,\\n    address owner\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return _verifyAccountOwner(account, owner);\\n  }\\n\\n  /**\\n   * @notice Verifies the owner of the account at a specific block\\n   * @param account account address\\n   * @param owner owner address\\n   * @param blockNumber block number to verify\\n   * @return true on correct account owner\\n   */\\n  function verifyAccountOwnerAtBlock(\\n    address account,\\n    address owner,\\n    uint256 blockNumber\\n  )\\n    external\\n    view\\n    returns (bool)\\n  {\\n    bool result = false;\\n\\n    if (_verifyAccountOwner(account, owner)) {\\n      result = true;\\n    } else {\\n      result = accounts[account].owners[owner].verifyAtBlock(blockNumber);\\n    }\\n\\n    return result;\\n  }\\n\\n  /**\\n   * @notice Verifies account signature\\n   * @param account account address\\n   * @param messageHash message hash\\n   * @param signature signature\\n   * @return magic hash if valid\\n   */\\n  function isValidAccountSignature(\\n    address account,\\n    bytes32 messageHash,\\n    bytes calldata signature\\n  )\\n    override\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return _verifyAccountOwner(\\n      account,\\n      messageHash.recoverAddress(signature)\\n    );\\n  }\\n\\n  /**\\n   * @notice Verifies account signature\\n   * @param account account address\\n   * @param message message\\n   * @param signature signature\\n   * @return magic hash if valid\\n   */\\n  function isValidAccountSignature(\\n    address account,\\n    bytes calldata message,\\n    bytes calldata signature\\n  )\\n    override\\n    external\\n    view\\n    returns (bool)\\n  {\\n    return _verifyAccountOwner(\\n      account,\\n      message.toEthereumSignedMessageHash().recoverAddress(signature)\\n    );\\n  }\\n\\n  // private functions\\n\\n  function _verifySender(\\n    address account\\n  )\\n    private\\n    returns (address)\\n  {\\n    address sender = _getContextSender();\\n\\n    if (accounts[account].owners[sender].added) {\\n      require(\\n        accounts[account].owners[sender].removedAtBlockNumber == 0,\\n        \\\"PersonalAccountRegistry: sender is not the account owner\\\"\\n      );\\n    } else {\\n      require(\\n        accounts[account].salt == 0,\\n        \\\"PersonalAccountRegistry: sender is not the account owner\\\"\\n      );\\n\\n      bytes32 salt = keccak256(\\n        abi.encodePacked(sender)\\n      );\\n\\n      require(\\n        account == _computeAccountAddress(salt),\\n        \\\"PersonalAccountRegistry: sender is not the account owner\\\"\\n      );\\n\\n      accounts[account].salt = salt;\\n      accounts[account].owners[sender].added = true;\\n\\n      emit AccountOwnerAdded(\\n        account,\\n        sender\\n      );\\n    }\\n\\n    return sender;\\n  }\\n\\n  function _deployAccount(\\n    address account\\n  )\\n    internal\\n  {\\n    if (!accounts[account].deployed) {\\n      _deployAccount(\\n        accounts[account].salt,\\n        true\\n      );\\n\\n      accounts[account].deployed = true;\\n    }\\n  }\\n\\n  // private functions (views)\\n\\n  function _computeAccountAddress(\\n    address saltOwner\\n  )\\n    private\\n    view\\n    returns (address)\\n  {\\n    bytes32 salt = keccak256(\\n      abi.encodePacked(saltOwner)\\n    );\\n\\n    return _computeAccountAddress(salt);\\n  }\\n\\n  function _verifyAccountOwner(\\n    address account,\\n    address owner\\n  )\\n    private\\n    view\\n    returns (bool)\\n  {\\n    bool result;\\n\\n    if (accounts[account].owners[owner].added) {\\n      result = accounts[account].owners[owner].removedAtBlockNumber == 0;\\n    } else if (accounts[account].salt == 0) {\\n      result = account == _computeAccountAddress(owner);\\n    }\\n\\n    return result;\\n  }\\n}\\n\",\"keccak256\":\"0xdae162610e707ab8c394b3edf924b75ef1f315520935cb88f4280b29eeaf4b61\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600046905080600181905550506123f58061006d6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063867519c61161008c5780639f255626116100665780639f255626146101fe578063b5021b161461021a578063d2c83b9a14610236578063f92c5f7c14610254576100cf565b8063867519c6146101a657806387d31313146101c25780639a8a0592146101e0576100cf565b8063231badaf146100d4578063392e53cd146100f0578063485cc9551461010e5780635afaa7bb1461012a57806373e5a13f1461014657806376db2b4c14610176575b600080fd5b6100ee60048036038101906100e99190611438565b610284565b005b6100f861037f565b6040516101059190611e71565b60405180910390f35b610128600480360381019061012391906115e0565b6103d5565b005b610144600480360381019061013f9190611563565b610561565b005b610160600480360381019061015b919061165d565b610739565b60405161016d9190611e8c565b60405180910390f35b610190600480360381019061018b919061161c565b61075e565b60405161019d9190611e8c565b60405180910390f35b6101c060048036038101906101bb91906113b9565b610788565b005b6101ca610799565b6040516101d79190611f07565b60405180910390f35b6101e86107bf565b6040516101f591906120a2565b60405180910390f35b610218600480360381019061021391906114f7565b6107c5565b005b610234600480360381019061022f9190611438565b6107d5565b005b61023e6108d1565b60405161024b9190611eec565b60405180910390f35b61026e60048036038101906102699190611390565b6108f7565b60405161027b91906120a2565b60405180910390f35b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fc90611f82565b60405180910390fd5b60006103258261031788888888610953565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061037786828686610a71565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045a90611f42565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516105559190611def565b60405180910390a15050565b60008251116105a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059c90611fc2565b60405180910390fd5b600080600090505b83518110156106f35760003073ffffffffffffffffffffffffffffffffffffffff168583815181106105db57fe5b60200260200101516040516105f09190611d0b565b6000604051808303816000865af19150503d806000811461062d576040519150601f19603f3d011682016040523d82523d6000602084013e610632565b606091505b505090508315610681578061067c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067390611f62565b60405180910390fd5b610697565b80801561068c575082155b1561069657600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106106c557fe5b6020026020010151836040516106dd93929190611e0a565b60405180910390a15080806001019150506105ad565b5080610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072b90612082565b60405180910390fd5b505050565b60006107578260000151836020015184604001518560600151610953565b9050919050565b600061078182600001518360200151846040015185606001518660800151610edc565b9050919050565b61079483338484610a71565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b6107d133338484610a71565b5050565b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084d90611f82565b60405180910390fd5b600061087782610869888888883a610edc565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108c986828686610a71565b505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061094c6001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f4290919063ffffffff16565b9050919050565b60006109ac7f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661098587610f97565b6040516020016109989493929190611c6e565b604051602081830303815290604052610ffa565b9050949350505050565b60008060009050604183511415610a675760008060006020860151925060408601519150606086015160001a9050601b8160ff1610156109f757601b810190505b601b8160ff161480610a0c5750601c8160ff16145b15610a635760018782858560405160008152602001604052604051610a349493929190611ea7565b6020604051602081039080840390855afa158015610a56573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415610ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad890611fa2565b60405180910390fd5b6000825111610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c90612062565b60405180910390fd5b8151815114610b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6090612002565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610d3d57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610bf9929190611e48565b60206040518083038186803b158015610c1157600080fd5b505afa158015610c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4991906115b7565b80610cfd5750600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610cac929190611e48565b60206040518083038186803b158015610cc457600080fd5b505afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc91906115b7565b5b610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3390611fe2565b60405180910390fd5b5b600080600090505b8251811015610ed457600073ffffffffffffffffffffffffffffffffffffffff16848281518110610d7257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff161415610dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc890611f22565b60405180910390fd5b838181518110610ddd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16838281518110610e0757fe5b60200260200101518787604051602001610e2393929190611d22565b604051602081830303815290604052604051610e3f9190611d0b565b6000604051808303816000865af19150503d8060008114610e7c576040519150601f19603f3d011682016040523d82523d6000602084013e610e81565b606091505b50508092505081610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebe90612022565b60405180910390fd5b8080600101915050610d45565b505050505050565b6000610f377f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad878787610f0e88610f97565b87604051602001610f23959493929190611cb4565b604051602081830303815290604052610ffa565b905095945050505050565b600080828401905083811015610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490612042565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015610fef5782858281518110610fb857fe5b6020026020010151604051602001610fd1929190611d5b565b60405160208183030381529060405292508080600101915050610fa3565b508192505050919050565b60006110336001543085856040516020016110189493929190611da5565b6040516020818303038152906040528051906020012061103b565b905092915050565b60008160405160200161104e9190611d7f565b604051602081830303815290604052805190602001209050919050565b60008135905061107a81612375565b92915050565b600082601f83011261109157600080fd5b81356110a461109f826120ea565b6120bd565b915081818352602084019350602081019050838560208402820111156110c957600080fd5b60005b838110156110f957816110df888261106b565b8452602084019350602083019250506001810190506110cc565b5050505092915050565b600082601f83011261111457600080fd5b813561112761112282612112565b6120bd565b9150818183526020840193506020810190508360005b8381101561116d578135860161115388826111a1565b84526020840193506020830192505060018101905061113d565b5050505092915050565b6000813590506111868161238c565b92915050565b60008151905061119b8161238c565b92915050565b600082601f8301126111b257600080fd5b81356111c56111c08261213a565b6120bd565b915080825260208301602083018583830111156111e157600080fd5b6111ec8382846122dd565b50505092915050565b600081359050611204816123a3565b92915050565b600081359050611219816123ba565b92915050565b600060a0828403121561123157600080fd5b61123b60a06120bd565b9050600061124b8482850161106b565b600083015250602061125f8482850161137b565b602083015250604082013567ffffffffffffffff81111561127f57600080fd5b61128b84828501611080565b604083015250606082013567ffffffffffffffff8111156112ab57600080fd5b6112b784828501611103565b60608301525060806112cb8482850161137b565b60808301525092915050565b6000608082840312156112e957600080fd5b6112f360806120bd565b905060006113038482850161106b565b60008301525060206113178482850161137b565b602083015250604082013567ffffffffffffffff81111561133757600080fd5b61134384828501611080565b604083015250606082013567ffffffffffffffff81111561136357600080fd5b61136f84828501611103565b60608301525092915050565b60008135905061138a816123d1565b92915050565b6000602082840312156113a257600080fd5b60006113b08482850161106b565b91505092915050565b6000806000606084860312156113ce57600080fd5b60006113dc8682870161106b565b935050602084013567ffffffffffffffff8111156113f957600080fd5b61140586828701611080565b925050604084013567ffffffffffffffff81111561142257600080fd5b61142e86828701611103565b9150509250925092565b600080600080600060a0868803121561145057600080fd5b600061145e8882890161106b565b955050602061146f8882890161137b565b945050604086013567ffffffffffffffff81111561148c57600080fd5b61149888828901611080565b935050606086013567ffffffffffffffff8111156114b557600080fd5b6114c188828901611103565b925050608086013567ffffffffffffffff8111156114de57600080fd5b6114ea888289016111a1565b9150509295509295909350565b6000806040838503121561150a57600080fd5b600083013567ffffffffffffffff81111561152457600080fd5b61153085828601611080565b925050602083013567ffffffffffffffff81111561154d57600080fd5b61155985828601611103565b9150509250929050565b6000806040838503121561157657600080fd5b600083013567ffffffffffffffff81111561159057600080fd5b61159c85828601611103565b92505060206115ad85828601611177565b9150509250929050565b6000602082840312156115c957600080fd5b60006115d78482850161118c565b91505092915050565b600080604083850312156115f357600080fd5b6000611601858286016111f5565b92505060206116128582860161120a565b9150509250929050565b60006020828403121561162e57600080fd5b600082013567ffffffffffffffff81111561164857600080fd5b6116548482850161121f565b91505092915050565b60006020828403121561166f57600080fd5b600082013567ffffffffffffffff81111561168957600080fd5b611695848285016112d7565b91505092915050565b60006116aa83836116d4565b60208301905092915050565b6116bf8161225f565b82525050565b6116ce816121dc565b82525050565b6116dd816121dc565b82525050565b6116f46116ef826121dc565b61231f565b82525050565b600061170582612176565b61170f8185612199565b935061171a83612166565b8060005b8381101561174b578151611732888261169e565b975061173d8361218c565b92505060018101905061171e565b5085935050505092915050565b611761816121ee565b82525050565b611770816121fa565b82525050565b611787611782826121fa565b612331565b82525050565b600061179882612181565b6117a281856121a4565b93506117b28185602086016122ec565b6117bb81612357565b840191505092915050565b60006117d182612181565b6117db81856121b5565b93506117eb8185602086016122ec565b80840191505092915050565b61180081612271565b82525050565b61180f81612295565b82525050565b6000611822601b836121c0565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000611862601c836121d1565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006118a2602f836121c0565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006119086017836121c0565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006119486032836121c0565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b60006119ae6025836121c0565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a146026836121c0565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a7a6028836121c0565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ae06016836121c0565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000611b206023836121c0565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611b86601e836121c0565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000611bc66020836121c0565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b6000611c06601d836121c0565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b611c4281612248565b82525050565b611c59611c5482612248565b61234d565b82525050565b611c6881612252565b82525050565b6000611c7a82876116e3565b601482019150611c8a8286611c48565b602082019150611c9a82856116fa565b9150611ca682846117c6565b915081905095945050505050565b6000611cc082886116e3565b601482019150611cd08287611c48565b602082019150611ce082866116fa565b9150611cec82856117c6565b9150611cf88284611c48565b6020820191508190509695505050505050565b6000611d1782846117c6565b915081905092915050565b6000611d2e82866117c6565b9150611d3a82856116e3565b601482019150611d4a82846116e3565b601482019150819050949350505050565b6000611d6782856117c6565b9150611d7382846117c6565b91508190509392505050565b6000611d8a82611855565b9150611d968284611776565b60208201915081905092915050565b6000611db18287611c48565b602082019150611dc182866116e3565b601482019150611dd18285611776565b602082019150611de182846117c6565b915081905095945050505050565b6000602082019050611e0460008301846116b6565b92915050565b6000606082019050611e1f60008301866116b6565b8181036020830152611e31818561178d565b9050611e406040830184611758565b949350505050565b6000604082019050611e5d60008301856116c5565b611e6a60208301846116c5565b9392505050565b6000602082019050611e866000830184611758565b92915050565b6000602082019050611ea16000830184611767565b92915050565b6000608082019050611ebc6000830187611767565b611ec96020830186611c5f565b611ed66040830185611767565b611ee36060830184611767565b95945050505050565b6000602082019050611f0160008301846117f7565b92915050565b6000602082019050611f1c6000830184611806565b92915050565b60006020820190508181036000830152611f3b81611815565b9050919050565b60006020820190508181036000830152611f5b81611895565b9050919050565b60006020820190508181036000830152611f7b816118fb565b9050919050565b60006020820190508181036000830152611f9b8161193b565b9050919050565b60006020820190508181036000830152611fbb816119a1565b9050919050565b60006020820190508181036000830152611fdb81611a07565b9050919050565b60006020820190508181036000830152611ffb81611a6d565b9050919050565b6000602082019050818103600083015261201b81611ad3565b9050919050565b6000602082019050818103600083015261203b81611b13565b9050919050565b6000602082019050818103600083015261205b81611b79565b9050919050565b6000602082019050818103600083015261207b81611bb9565b9050919050565b6000602082019050818103600083015261209b81611bf9565b9050919050565b60006020820190506120b76000830184611c39565b92915050565b6000604051905081810181811067ffffffffffffffff821117156120e057600080fd5b8060405250919050565b600067ffffffffffffffff82111561210157600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561212957600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561215157600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006121e782612228565b9050919050565b60008115159050919050565b6000819050919050565b600061220f826121dc565b9050919050565b6000612221826121dc565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061226a826122b9565b9050919050565b600061227c82612283565b9050919050565b600061228e82612228565b9050919050565b60006122a0826122a7565b9050919050565b60006122b282612228565b9050919050565b60006122c4826122cb565b9050919050565b60006122d682612228565b9050919050565b82818337600083830152505050565b60005b8381101561230a5780820151818401526020810190506122ef565b83811115612319576000848401525b50505050565b600061232a8261233b565b9050919050565b6000819050919050565b600061234682612368565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61237e816121dc565b811461238957600080fd5b50565b612395816121ee565b81146123a057600080fd5b50565b6123ac81612204565b81146123b757600080fd5b50565b6123c381612216565b81146123ce57600080fd5b50565b6123da81612248565b81146123e557600080fd5b5056fea164736f6c634300060c000a",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063867519c61161008c5780639f255626116100665780639f255626146101fe578063b5021b161461021a578063d2c83b9a14610236578063f92c5f7c14610254576100cf565b8063867519c6146101a657806387d31313146101c25780639a8a0592146101e0576100cf565b8063231badaf146100d4578063392e53cd146100f0578063485cc9551461010e5780635afaa7bb1461012a57806373e5a13f1461014657806376db2b4c14610176575b600080fd5b6100ee60048036038101906100e99190611438565b610284565b005b6100f861037f565b6040516101059190611e71565b60405180910390f35b610128600480360381019061012391906115e0565b6103d5565b005b610144600480360381019061013f9190611563565b610561565b005b610160600480360381019061015b919061165d565b610739565b60405161016d9190611e8c565b60405180910390f35b610190600480360381019061018b919061161c565b61075e565b60405161019d9190611e8c565b60405180910390f35b6101c060048036038101906101bb91906113b9565b610788565b005b6101ca610799565b6040516101d79190611f07565b60405180910390f35b6101e86107bf565b6040516101f591906120a2565b60405180910390f35b610218600480360381019061021391906114f7565b6107c5565b005b610234600480360381019061022f9190611438565b6107d5565b005b61023e6108d1565b60405161024b9190611eec565b60405180910390f35b61026e60048036038101906102699190611390565b6108f7565b60405161027b91906120a2565b60405180910390f35b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fc90611f82565b60405180910390fd5b60006103258261031788888888610953565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061037786828686610a71565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045a90611f42565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516105559190611def565b60405180910390a15050565b60008251116105a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059c90611fc2565b60405180910390fd5b600080600090505b83518110156106f35760003073ffffffffffffffffffffffffffffffffffffffff168583815181106105db57fe5b60200260200101516040516105f09190611d0b565b6000604051808303816000865af19150503d806000811461062d576040519150601f19603f3d011682016040523d82523d6000602084013e610632565b606091505b505090508315610681578061067c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067390611f62565b60405180910390fd5b610697565b80801561068c575082155b1561069657600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106106c557fe5b6020026020010151836040516106dd93929190611e0a565b60405180910390a15080806001019150506105ad565b5080610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072b90612082565b60405180910390fd5b505050565b60006107578260000151836020015184604001518560600151610953565b9050919050565b600061078182600001518360200151846040015185606001518660800151610edc565b9050919050565b61079483338484610a71565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b6107d133338484610a71565b5050565b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084d90611f82565b60405180910390fd5b600061087782610869888888883a610edc565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108c986828686610a71565b505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061094c6001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f4290919063ffffffff16565b9050919050565b60006109ac7f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661098587610f97565b6040516020016109989493929190611c6e565b604051602081830303815290604052610ffa565b9050949350505050565b60008060009050604183511415610a675760008060006020860151925060408601519150606086015160001a9050601b8160ff1610156109f757601b810190505b601b8160ff161480610a0c5750601c8160ff16145b15610a635760018782858560405160008152602001604052604051610a349493929190611ea7565b6020604051602081039080840390855afa158015610a56573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415610ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad890611fa2565b60405180910390fd5b6000825111610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c90612062565b60405180910390fd5b8151815114610b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6090612002565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610d3d57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610bf9929190611e48565b60206040518083038186803b158015610c1157600080fd5b505afa158015610c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4991906115b7565b80610cfd5750600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610cac929190611e48565b60206040518083038186803b158015610cc457600080fd5b505afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc91906115b7565b5b610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3390611fe2565b60405180910390fd5b5b600080600090505b8251811015610ed457600073ffffffffffffffffffffffffffffffffffffffff16848281518110610d7257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff161415610dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc890611f22565b60405180910390fd5b838181518110610ddd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16838281518110610e0757fe5b60200260200101518787604051602001610e2393929190611d22565b604051602081830303815290604052604051610e3f9190611d0b565b6000604051808303816000865af19150503d8060008114610e7c576040519150601f19603f3d011682016040523d82523d6000602084013e610e81565b606091505b50508092505081610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebe90612022565b60405180910390fd5b8080600101915050610d45565b505050505050565b6000610f377f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad878787610f0e88610f97565b87604051602001610f23959493929190611cb4565b604051602081830303815290604052610ffa565b905095945050505050565b600080828401905083811015610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490612042565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015610fef5782858281518110610fb857fe5b6020026020010151604051602001610fd1929190611d5b565b60405160208183030381529060405292508080600101915050610fa3565b508192505050919050565b60006110336001543085856040516020016110189493929190611da5565b6040516020818303038152906040528051906020012061103b565b905092915050565b60008160405160200161104e9190611d7f565b604051602081830303815290604052805190602001209050919050565b60008135905061107a81612375565b92915050565b600082601f83011261109157600080fd5b81356110a461109f826120ea565b6120bd565b915081818352602084019350602081019050838560208402820111156110c957600080fd5b60005b838110156110f957816110df888261106b565b8452602084019350602083019250506001810190506110cc565b5050505092915050565b600082601f83011261111457600080fd5b813561112761112282612112565b6120bd565b9150818183526020840193506020810190508360005b8381101561116d578135860161115388826111a1565b84526020840193506020830192505060018101905061113d565b5050505092915050565b6000813590506111868161238c565b92915050565b60008151905061119b8161238c565b92915050565b600082601f8301126111b257600080fd5b81356111c56111c08261213a565b6120bd565b915080825260208301602083018583830111156111e157600080fd5b6111ec8382846122dd565b50505092915050565b600081359050611204816123a3565b92915050565b600081359050611219816123ba565b92915050565b600060a0828403121561123157600080fd5b61123b60a06120bd565b9050600061124b8482850161106b565b600083015250602061125f8482850161137b565b602083015250604082013567ffffffffffffffff81111561127f57600080fd5b61128b84828501611080565b604083015250606082013567ffffffffffffffff8111156112ab57600080fd5b6112b784828501611103565b60608301525060806112cb8482850161137b565b60808301525092915050565b6000608082840312156112e957600080fd5b6112f360806120bd565b905060006113038482850161106b565b60008301525060206113178482850161137b565b602083015250604082013567ffffffffffffffff81111561133757600080fd5b61134384828501611080565b604083015250606082013567ffffffffffffffff81111561136357600080fd5b61136f84828501611103565b60608301525092915050565b60008135905061138a816123d1565b92915050565b6000602082840312156113a257600080fd5b60006113b08482850161106b565b91505092915050565b6000806000606084860312156113ce57600080fd5b60006113dc8682870161106b565b935050602084013567ffffffffffffffff8111156113f957600080fd5b61140586828701611080565b925050604084013567ffffffffffffffff81111561142257600080fd5b61142e86828701611103565b9150509250925092565b600080600080600060a0868803121561145057600080fd5b600061145e8882890161106b565b955050602061146f8882890161137b565b945050604086013567ffffffffffffffff81111561148c57600080fd5b61149888828901611080565b935050606086013567ffffffffffffffff8111156114b557600080fd5b6114c188828901611103565b925050608086013567ffffffffffffffff8111156114de57600080fd5b6114ea888289016111a1565b9150509295509295909350565b6000806040838503121561150a57600080fd5b600083013567ffffffffffffffff81111561152457600080fd5b61153085828601611080565b925050602083013567ffffffffffffffff81111561154d57600080fd5b61155985828601611103565b9150509250929050565b6000806040838503121561157657600080fd5b600083013567ffffffffffffffff81111561159057600080fd5b61159c85828601611103565b92505060206115ad85828601611177565b9150509250929050565b6000602082840312156115c957600080fd5b60006115d78482850161118c565b91505092915050565b600080604083850312156115f357600080fd5b6000611601858286016111f5565b92505060206116128582860161120a565b9150509250929050565b60006020828403121561162e57600080fd5b600082013567ffffffffffffffff81111561164857600080fd5b6116548482850161121f565b91505092915050565b60006020828403121561166f57600080fd5b600082013567ffffffffffffffff81111561168957600080fd5b611695848285016112d7565b91505092915050565b60006116aa83836116d4565b60208301905092915050565b6116bf8161225f565b82525050565b6116ce816121dc565b82525050565b6116dd816121dc565b82525050565b6116f46116ef826121dc565b61231f565b82525050565b600061170582612176565b61170f8185612199565b935061171a83612166565b8060005b8381101561174b578151611732888261169e565b975061173d8361218c565b92505060018101905061171e565b5085935050505092915050565b611761816121ee565b82525050565b611770816121fa565b82525050565b611787611782826121fa565b612331565b82525050565b600061179882612181565b6117a281856121a4565b93506117b28185602086016122ec565b6117bb81612357565b840191505092915050565b60006117d182612181565b6117db81856121b5565b93506117eb8185602086016122ec565b80840191505092915050565b61180081612271565b82525050565b61180f81612295565b82525050565b6000611822601b836121c0565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000611862601c836121d1565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006118a2602f836121c0565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006119086017836121c0565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006119486032836121c0565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b60006119ae6025836121c0565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a146026836121c0565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a7a6028836121c0565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ae06016836121c0565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000611b206023836121c0565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611b86601e836121c0565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000611bc66020836121c0565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b6000611c06601d836121c0565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b611c4281612248565b82525050565b611c59611c5482612248565b61234d565b82525050565b611c6881612252565b82525050565b6000611c7a82876116e3565b601482019150611c8a8286611c48565b602082019150611c9a82856116fa565b9150611ca682846117c6565b915081905095945050505050565b6000611cc082886116e3565b601482019150611cd08287611c48565b602082019150611ce082866116fa565b9150611cec82856117c6565b9150611cf88284611c48565b6020820191508190509695505050505050565b6000611d1782846117c6565b915081905092915050565b6000611d2e82866117c6565b9150611d3a82856116e3565b601482019150611d4a82846116e3565b601482019150819050949350505050565b6000611d6782856117c6565b9150611d7382846117c6565b91508190509392505050565b6000611d8a82611855565b9150611d968284611776565b60208201915081905092915050565b6000611db18287611c48565b602082019150611dc182866116e3565b601482019150611dd18285611776565b602082019150611de182846117c6565b915081905095945050505050565b6000602082019050611e0460008301846116b6565b92915050565b6000606082019050611e1f60008301866116b6565b8181036020830152611e31818561178d565b9050611e406040830184611758565b949350505050565b6000604082019050611e5d60008301856116c5565b611e6a60208301846116c5565b9392505050565b6000602082019050611e866000830184611758565b92915050565b6000602082019050611ea16000830184611767565b92915050565b6000608082019050611ebc6000830187611767565b611ec96020830186611c5f565b611ed66040830185611767565b611ee36060830184611767565b95945050505050565b6000602082019050611f0160008301846117f7565b92915050565b6000602082019050611f1c6000830184611806565b92915050565b60006020820190508181036000830152611f3b81611815565b9050919050565b60006020820190508181036000830152611f5b81611895565b9050919050565b60006020820190508181036000830152611f7b816118fb565b9050919050565b60006020820190508181036000830152611f9b8161193b565b9050919050565b60006020820190508181036000830152611fbb816119a1565b9050919050565b60006020820190508181036000830152611fdb81611a07565b9050919050565b60006020820190508181036000830152611ffb81611a6d565b9050919050565b6000602082019050818103600083015261201b81611ad3565b9050919050565b6000602082019050818103600083015261203b81611b13565b9050919050565b6000602082019050818103600083015261205b81611b79565b9050919050565b6000602082019050818103600083015261207b81611bb9565b9050919050565b6000602082019050818103600083015261209b81611bf9565b9050919050565b60006020820190506120b76000830184611c39565b92915050565b6000604051905081810181811067ffffffffffffffff821117156120e057600080fd5b8060405250919050565b600067ffffffffffffffff82111561210157600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561212957600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561215157600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006121e782612228565b9050919050565b60008115159050919050565b6000819050919050565b600061220f826121dc565b9050919050565b6000612221826121dc565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061226a826122b9565b9050919050565b600061227c82612283565b9050919050565b600061228e82612228565b9050919050565b60006122a0826122a7565b9050919050565b60006122b282612228565b9050919050565b60006122c4826122cb565b9050919050565b60006122d682612228565b9050919050565b82818337600083830152505050565b60005b8381101561230a5780820151818401526020810190506122ef565b83811115612319576000848401525b50505050565b600061232a8261233b565b9050919050565b6000819050919050565b600061234682612368565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61237e816121dc565b811461238957600080fd5b50565b612395816121ee565b81146123a057600080fd5b50565b6123ac81612204565b81146123b757600080fd5b50565b6123c381612216565b81146123ce57600080fd5b50565b6123da81612248565b81146123e557600080fd5b5056fea164736f6c634300060c000a",
  "devdoc": {
    "author": "Stanisław Głogowski <stan@pillarproject.io>",
    "events": {
      "BatchDelegated(address,bytes,bool)": {
        "details": "Emitted when the single batch is delegated",
        "params": {
          "batch": "batch",
          "sender": "sender address",
          "succeeded": "if succeeded"
        }
      }
    },
    "kind": "dev",
    "methods": {
      "constructor": {
        "details": "Public constructor"
      },
      "delegateBatch(address,uint256,address[],bytes[],bytes)": {
        "details": "Use `hashDelegatedBatch` to create sender message payload. `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg",
        "params": {
          "account": "account address",
          "data": "array of batch data",
          "nonce": "next account nonce",
          "senderSignature": "sender signature",
          "to": "array of batch recipients contracts"
        }
      },
      "delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)": {
        "details": "Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice) `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg",
        "params": {
          "account": "account address",
          "data": "array of batch data",
          "nonce": "next account nonce",
          "senderSignature": "sender signature",
          "to": "array of batch recipients contracts"
        }
      },
      "delegateBatches(bytes[],bool)": {
        "details": "It will revert when all batches fail",
        "params": {
          "batches": "array of batches",
          "revertOnFailure": "reverts on any error"
        }
      },
      "getAccountNextNonce(address)": {
        "params": {
          "account": "account address"
        },
        "returns": {
          "_0": "next nonce"
        }
      },
      "hashDelegatedBatch((address,uint256,address[],bytes[]))": {
        "params": {
          "delegatedBatch": "struct"
        },
        "returns": {
          "_0": "hash"
        }
      },
      "hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))": {
        "params": {
          "delegatedBatch": "struct"
        },
        "returns": {
          "_0": "hash"
        }
      },
      "initialize(address,address)": {
        "params": {
          "externalAccountRegistry_": "`ExternalAccountRegistry` contract address",
          "personalAccountRegistry_": "`PersonalAccountRegistry` contract address"
        }
      },
      "isInitialized()": {
        "returns": {
          "_0": "true when contract is initialized"
        }
      },
      "sendBatch(address[],bytes[])": {
        "details": "`GatewayRecipient` context api: `_getContextAccount` will return `msg.sender` `_getContextSender` will return `msg.sender`",
        "params": {
          "data": "array of batch data",
          "to": "array of batch recipients contracts"
        }
      },
      "sendBatchFromAccount(address,address[],bytes[])": {
        "details": "`GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return `msg.sender`",
        "params": {
          "account": "account address",
          "data": "array of batch data",
          "to": "array of batch recipients contracts"
        }
      }
    },
    "title": "Gateway",
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "delegateBatch(address,uint256,address[],bytes[],bytes)": {
        "notice": "Delegates batch from the account"
      },
      "delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)": {
        "notice": "Delegates batch from the account (with gas price)"
      },
      "delegateBatches(bytes[],bool)": {
        "notice": "Delegates multiple batches"
      },
      "getAccountNextNonce(address)": {
        "notice": "Gets next account nonce"
      },
      "hashDelegatedBatch((address,uint256,address[],bytes[]))": {
        "notice": "Hashes `DelegatedBatch` message payload"
      },
      "hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))": {
        "notice": "Hashes `DelegatedBatchWithGasPrice` message payload"
      },
      "initialize(address,address)": {
        "notice": "Initializes `Gateway` contract"
      },
      "isInitialized()": {
        "notice": "Check if contract is initialized"
      },
      "sendBatch(address[],bytes[])": {
        "notice": "Sends batch"
      },
      "sendBatchFromAccount(address,address[],bytes[])": {
        "notice": "Sends batch from the account"
      }
    },
    "notice": "GSN replacement",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 1871,
        "contract": "src/gateway/Gateway.sol:Gateway",
        "label": "initializer",
        "offset": 0,
        "slot": "0",
        "type": "t_address"
      },
      {
        "astId": 1935,
        "contract": "src/gateway/Gateway.sol:Gateway",
        "label": "chainId",
        "offset": 0,
        "slot": "1",
        "type": "t_uint256"
      },
      {
        "astId": 4647,
        "contract": "src/gateway/Gateway.sol:Gateway",
        "label": "externalAccountRegistry",
        "offset": 0,
        "slot": "2",
        "type": "t_contract(ExternalAccountRegistry)4591"
      },
      {
        "astId": 4649,
        "contract": "src/gateway/Gateway.sol:Gateway",
        "label": "personalAccountRegistry",
        "offset": 0,
        "slot": "3",
        "type": "t_contract(PersonalAccountRegistry)7452"
      },
      {
        "astId": 4653,
        "contract": "src/gateway/Gateway.sol:Gateway",
        "label": "accountNonce",
        "offset": 0,
        "slot": "4",
        "type": "t_mapping(t_address,t_uint256)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_contract(ExternalAccountRegistry)4591": {
        "encoding": "inplace",
        "label": "contract ExternalAccountRegistry",
        "numberOfBytes": "20"
      },
      "t_contract(PersonalAccountRegistry)7452": {
        "encoding": "inplace",
        "label": "contract PersonalAccountRegistry",
        "numberOfBytes": "20"
      },
      "t_mapping(t_address,t_uint256)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}