{
  "address": "0x9FC4DdE698E5cf1Ee8d6e2D25c835836d9af1C8F",
  "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": "sender",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "guardian",
          "type": "address"
        }
      ],
      "name": "GuardianAdded",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "guardian",
          "type": "address"
        }
      ],
      "name": "GuardianRemoved",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "initializer",
          "type": "address"
        }
      ],
      "name": "Initialized",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "guardian",
          "type": "address"
        }
      ],
      "name": "addGuardian",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "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": "delegateBatchGuarded",
      "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": "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": "delegateBatchWithGasPriceGuarded",
      "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": [
        {
          "internalType": "bytes[]",
          "name": "batches",
          "type": "bytes[]"
        },
        {
          "internalType": "bool",
          "name": "revertOnFailure",
          "type": "bool"
        }
      ],
      "name": "delegateBatchesGuarded",
      "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 GatewayV2.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 GatewayV2.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": [
        {
          "internalType": "address",
          "name": "guardian",
          "type": "address"
        }
      ],
      "name": "isGuardian",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "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": "guardian",
          "type": "address"
        }
      ],
      "name": "removeGuardian",
      "outputs": [],
      "stateMutability": "nonpayable",
      "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"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "address[]",
          "name": "to",
          "type": "address[]"
        },
        {
          "internalType": "bytes[]",
          "name": "data",
          "type": "bytes[]"
        }
      ],
      "name": "sendBatchFromAccountGuarded",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "to",
          "type": "address[]"
        },
        {
          "internalType": "bytes[]",
          "name": "data",
          "type": "bytes[]"
        }
      ],
      "name": "sendBatchGuarded",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "messageHash",
          "type": "bytes32"
        },
        {
          "internalType": "bytes",
          "name": "signature",
          "type": "bytes"
        }
      ],
      "name": "verifyGuardianSignature",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "transactionHash": "0x8db8b0e7e1e833d4b9ef812bf06fb7338ac25b496447512b5677436a4640a8d0",
  "receipt": {
    "to": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",
    "from": "0x53fE9288897e254698175740aa359E19E26c10af",
    "contractAddress": null,
    "transactionIndex": 2,
    "gasUsed": "2822044",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xfe4c25b2817a331aa8dc2ba718006b403f3016aca4b4d7a7e3cbd68b65373c2f",
    "transactionHash": "0x8db8b0e7e1e833d4b9ef812bf06fb7338ac25b496447512b5677436a4640a8d0",
    "logs": [],
    "blockNumber": 14561647,
    "cumulativeGasUsed": "3198755",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "c3a4dcb3b63a7a4eb038de81f94876c9",
  "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\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"GuardianAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"GuardianRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"addGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\":\"delegateBatchGuarded\",\"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\":\"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\":\"delegateBatchWithGasPriceGuarded\",\"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\":[{\"internalType\":\"bytes[]\",\"name\":\"batches\",\"type\":\"bytes[]\"},{\"internalType\":\"bool\",\"name\":\"revertOnFailure\",\"type\":\"bool\"}],\"name\":\"delegateBatchesGuarded\",\"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 GatewayV2.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 GatewayV2.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\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"isGuardian\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":\"guardian\",\"type\":\"address\"}],\"name\":\"removeGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatchFromAccountGuarded\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatchGuarded\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"verifyGuardianSignature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Utkir Sobirov <sobirovutkir@gmail.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\":{\"addGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"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\"}},\"delegateBatchGuarded(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\"}},\"delegateBatchWithGasPriceGuarded(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\"}},\"delegateBatchesGuarded(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\"}},\"isGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"},\"returns\":{\"_0\":\"true when guardian exists\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"removeGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"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\"}},\"sendBatchFromAccountGuarded(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\"}},\"sendBatchGuarded(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\"}},\"verifyGuardianSignature(bytes32,bytes)\":{\"params\":{\"messageHash\":\"message hash\",\"signature\":\"signature\"},\"returns\":{\"_0\":\"true on correct guardian signature\"}}},\"title\":\"Gateway V2 with guarded batching functions\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addGuardian(address)\":{\"notice\":\"Adds a new guardian\"},\"delegateBatch(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account\"},\"delegateBatchGuarded(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates guarded batch from the account\"},\"delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account (with gas price)\"},\"delegateBatchWithGasPriceGuarded(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates guarded batch from the account (with gas price)\"},\"delegateBatches(bytes[],bool)\":{\"notice\":\"Delegates multiple batches\"},\"delegateBatchesGuarded(bytes[],bool)\":{\"notice\":\"Delegates multiple guarded 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\"},\"isGuardian(address)\":{\"notice\":\"Check if guardian exists\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"removeGuardian(address)\":{\"notice\":\"Removes the existing guardian\"},\"sendBatch(address[],bytes[])\":{\"notice\":\"Sends batch\"},\"sendBatchFromAccount(address,address[],bytes[])\":{\"notice\":\"Sends batch from the account\"},\"sendBatchFromAccountGuarded(address,address[],bytes[])\":{\"notice\":\"Sends guarded batch from the account\"},\"sendBatchGuarded(address[],bytes[])\":{\"notice\":\"Sends guarded batch\"},\"verifyGuardianSignature(bytes32,bytes)\":{\"notice\":\"Verifies guardian signature\"}},\"notice\":\"GSN replacement\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/gateway/GatewayV2.sol\":\"GatewayV2\"},\"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/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/gateway/GatewayV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\npragma solidity ^0.6.12;\\r\\npragma experimental ABIEncoderV2;\\r\\n\\r\\nimport \\\"../common/access/Guarded.sol\\\";\\r\\nimport \\\"../common/libs/ECDSALib.sol\\\";\\r\\nimport \\\"../common/libs/SafeMathLib.sol\\\";\\r\\nimport \\\"../common/lifecycle/Initializable.sol\\\";\\r\\nimport \\\"../common/signature/SignatureValidator.sol\\\";\\r\\nimport \\\"../external/ExternalAccountRegistry.sol\\\";\\r\\nimport \\\"../personal/PersonalAccountRegistry.sol\\\";\\r\\n\\r\\n/**\\r\\n * @title Gateway V2 with guarded batching functions\\r\\n *\\r\\n * @notice GSN replacement\\r\\n *\\r\\n * @author Utkir Sobirov <sobirovutkir@gmail.io>\\r\\n */\\r\\ncontract GatewayV2 is Initializable, SignatureValidator, Guarded {\\r\\n  using ECDSALib for bytes32;\\r\\n  using SafeMathLib for uint256;\\r\\n\\r\\n  struct DelegatedBatch {\\r\\n    address account;\\r\\n    uint256 nonce;\\r\\n    address[] to;\\r\\n    bytes[] data;\\r\\n  }\\r\\n\\r\\n  struct DelegatedBatchWithGasPrice {\\r\\n    address account;\\r\\n    uint256 nonce;\\r\\n    address[] to;\\r\\n    bytes[] data;\\r\\n    uint256 gasPrice;\\r\\n  }\\r\\n\\r\\n  bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256(\\r\\n    \\\"DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)\\\"\\r\\n  );\\r\\n\\r\\n  bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256(\\r\\n    \\\"DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)\\\"\\r\\n  );\\r\\n\\r\\n  ExternalAccountRegistry public externalAccountRegistry;\\r\\n  PersonalAccountRegistry public personalAccountRegistry;\\r\\n\\r\\n  mapping(address => uint256) private accountNonce;\\r\\n\\r\\n  // events\\r\\n\\r\\n  /**\\r\\n   * @dev Emitted when the single batch is delegated\\r\\n   * @param sender sender address\\r\\n   * @param batch batch\\r\\n   * @param succeeded if succeeded\\r\\n   */\\r\\n  event BatchDelegated(\\r\\n    address sender,\\r\\n    bytes batch,\\r\\n    bool succeeded\\r\\n  );\\r\\n\\r\\n  /**\\r\\n   * @dev Public constructor\\r\\n   */\\r\\n  constructor() public Initializable() SignatureValidator() {}\\r\\n\\r\\n  // external functions\\r\\n\\r\\n  /**\\r\\n   * @notice Initializes `Gateway` contract\\r\\n   * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\\r\\n   * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\\r\\n   */\\r\\n  function initialize(\\r\\n    ExternalAccountRegistry externalAccountRegistry_,\\r\\n    PersonalAccountRegistry personalAccountRegistry_\\r\\n  )\\r\\n    external\\r\\n    onlyInitializer\\r\\n  {\\r\\n    externalAccountRegistry = externalAccountRegistry_;\\r\\n    personalAccountRegistry = personalAccountRegistry_;\\r\\n\\r\\n    address[] memory guardians;\\r\\n    _initializeGuarded(guardians); // adds tx.origin to guardians list\\r\\n  }\\r\\n\\r\\n  // public functions\\r\\n\\r\\n  /**\\r\\n   * @notice Sends batch\\r\\n   * @dev `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `msg.sender`\\r\\n   * `_getContextSender` will return `msg.sender`\\r\\n   *\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   */\\r\\n  function sendBatch(\\r\\n    address[] memory to,\\r\\n    bytes[] memory data\\r\\n  )\\r\\n    public\\r\\n  {\\r\\n    _sendBatch(\\r\\n      msg.sender,\\r\\n      msg.sender,\\r\\n      to,\\r\\n      data\\r\\n    );\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Sends guarded batch\\r\\n   * @dev `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `msg.sender`\\r\\n   * `_getContextSender` will return `msg.sender`\\r\\n   *\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   */\\r\\n  function sendBatchGuarded(\\r\\n    address[] memory to,\\r\\n    bytes[] memory data\\r\\n  )\\r\\n    public\\r\\n    onlyGuardian\\r\\n  {\\r\\n    sendBatch(to, data);\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Sends batch from the account\\r\\n   * @dev `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `account` arg\\r\\n   * `_getContextSender` will return `msg.sender`\\r\\n   *\\r\\n   * @param account account address\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   */\\r\\n  function sendBatchFromAccount(\\r\\n    address account,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data\\r\\n  )\\r\\n    public\\r\\n  {\\r\\n    _sendBatch(\\r\\n      account,\\r\\n      msg.sender,\\r\\n      to,\\r\\n      data\\r\\n    );\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Sends guarded batch from the account\\r\\n   * @dev `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `account` arg\\r\\n   * `_getContextSender` will return `msg.sender`\\r\\n   *\\r\\n   * @param account account address\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   */\\r\\n  function sendBatchFromAccountGuarded(\\r\\n    address account,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data\\r\\n  )\\r\\n    public\\r\\n    onlyGuardian\\r\\n  {\\r\\n    sendBatchFromAccount(account, to, data);\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Delegates batch from the account\\r\\n   * @dev Use `hashDelegatedBatch` to create sender message payload.\\r\\n   *\\r\\n   * `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `account` arg\\r\\n   * `_getContextSender` will return recovered address from `senderSignature` arg\\r\\n   *\\r\\n   * @param account account address\\r\\n   * @param nonce next account nonce\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   * @param senderSignature sender signature\\r\\n   */\\r\\n  function delegateBatch(\\r\\n    address account,\\r\\n    uint256 nonce,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data,\\r\\n    bytes memory senderSignature\\r\\n  )\\r\\n    public\\r\\n  {\\r\\n    require(\\r\\n      nonce > accountNonce[account],\\r\\n      \\\"Gateway: nonce is lower than current account nonce\\\"\\r\\n    );\\r\\n\\r\\n    address sender = _hashDelegatedBatch(\\r\\n      account,\\r\\n      nonce,\\r\\n      to,\\r\\n      data\\r\\n    ).recoverAddress(senderSignature);\\r\\n\\r\\n    accountNonce[account] = nonce;\\r\\n\\r\\n    _sendBatch(\\r\\n      account,\\r\\n      sender,\\r\\n      to,\\r\\n      data\\r\\n    );\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Delegates guarded batch from the account\\r\\n   * @dev Use `hashDelegatedBatch` to create sender message payload.\\r\\n   *\\r\\n   * `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `account` arg\\r\\n   * `_getContextSender` will return recovered address from `senderSignature` arg\\r\\n   *\\r\\n   * @param account account address\\r\\n   * @param nonce next account nonce\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   * @param senderSignature sender signature\\r\\n   */\\r\\n  function delegateBatchGuarded(\\r\\n    address account,\\r\\n    uint256 nonce,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data,\\r\\n    bytes memory senderSignature\\r\\n  )\\r\\n    public\\r\\n    onlyGuardian\\r\\n  {\\r\\n    delegateBatch(account, nonce, to, data, senderSignature);\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Delegates batch from the account (with gas price)\\r\\n   *\\r\\n   * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\\r\\n   *\\r\\n   * `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `account` arg\\r\\n   * `_getContextSender` will return recovered address from `senderSignature` arg\\r\\n   *\\r\\n   * @param account account address\\r\\n   * @param nonce next account nonce\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   * @param senderSignature sender signature\\r\\n   */\\r\\n  function delegateBatchWithGasPrice(\\r\\n    address account,\\r\\n    uint256 nonce,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data,\\r\\n    bytes memory senderSignature\\r\\n  )\\r\\n    public\\r\\n  {\\r\\n    require(\\r\\n      nonce > accountNonce[account],\\r\\n      \\\"Gateway: nonce is lower than current account nonce\\\"\\r\\n    );\\r\\n\\r\\n    address sender = _hashDelegatedBatchWithGasPrice(\\r\\n      account,\\r\\n      nonce,\\r\\n      to,\\r\\n      data,\\r\\n      tx.gasprice\\r\\n    ).recoverAddress(senderSignature);\\r\\n\\r\\n    accountNonce[account] = nonce;\\r\\n\\r\\n    _sendBatch(\\r\\n      account,\\r\\n      sender,\\r\\n      to,\\r\\n      data\\r\\n    );\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Delegates guarded batch from the account (with gas price)\\r\\n   *\\r\\n   * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\\r\\n   *\\r\\n   * `GatewayRecipient` context api:\\r\\n   * `_getContextAccount` will return `account` arg\\r\\n   * `_getContextSender` will return recovered address from `senderSignature` arg\\r\\n   *\\r\\n   * @param account account address\\r\\n   * @param nonce next account nonce\\r\\n   * @param to array of batch recipients contracts\\r\\n   * @param data array of batch data\\r\\n   * @param senderSignature sender signature\\r\\n   */\\r\\n  function delegateBatchWithGasPriceGuarded(\\r\\n    address account,\\r\\n    uint256 nonce,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data,\\r\\n    bytes memory senderSignature\\r\\n  )\\r\\n    public\\r\\n    onlyGuardian\\r\\n  {\\r\\n    delegateBatchWithGasPrice(account, nonce, to, data, senderSignature);\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Delegates multiple batches\\r\\n   * @dev It will revert when all batches fail\\r\\n   * @param batches array of batches\\r\\n   * @param revertOnFailure reverts on any error\\r\\n   */\\r\\n  function delegateBatches(\\r\\n    bytes[] memory batches,\\r\\n    bool revertOnFailure\\r\\n  )\\r\\n    public\\r\\n  {\\r\\n    require(\\r\\n      batches.length > 0,\\r\\n      \\\"Gateway: cannot delegate empty batches\\\"\\r\\n    );\\r\\n\\r\\n    bool anySucceeded;\\r\\n\\r\\n    for (uint256 i = 0; i < batches.length; i++) {\\r\\n      // solhint-disable-next-line avoid-low-level-calls\\r\\n      (bool succeeded,) = address(this).call(batches[i]);\\r\\n\\r\\n      if (revertOnFailure) {\\r\\n        require(\\r\\n          succeeded,\\r\\n          \\\"Gateway: batch reverted\\\"\\r\\n        );\\r\\n      } else if (succeeded && !anySucceeded) {\\r\\n        anySucceeded = true;\\r\\n      }\\r\\n\\r\\n      emit BatchDelegated(\\r\\n        msg.sender,\\r\\n        batches[i],\\r\\n        succeeded\\r\\n      );\\r\\n    }\\r\\n\\r\\n    if (!anySucceeded) {\\r\\n      revert(\\\"Gateway: all batches reverted\\\");\\r\\n    }\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Delegates multiple guarded batches\\r\\n   * @dev It will revert when all batches fail\\r\\n   * @param batches array of batches\\r\\n   * @param revertOnFailure reverts on any error\\r\\n   */\\r\\n  function delegateBatchesGuarded(\\r\\n    bytes[] memory batches,\\r\\n    bool revertOnFailure\\r\\n  )\\r\\n    public\\r\\n    onlyGuardian\\r\\n  {\\r\\n    delegateBatches(batches, revertOnFailure);\\r\\n  }\\r\\n\\r\\n  // public functions (views)\\r\\n\\r\\n  /**\\r\\n   * @notice Hashes `DelegatedBatch` message payload\\r\\n   * @param delegatedBatch struct\\r\\n   * @return hash\\r\\n   */\\r\\n  function hashDelegatedBatch(\\r\\n    DelegatedBatch memory delegatedBatch\\r\\n  )\\r\\n    public\\r\\n    view\\r\\n    returns (bytes32)\\r\\n  {\\r\\n    return _hashDelegatedBatch(\\r\\n      delegatedBatch.account,\\r\\n      delegatedBatch.nonce,\\r\\n      delegatedBatch.to,\\r\\n      delegatedBatch.data\\r\\n    );\\r\\n  }\\r\\n\\r\\n  /**\\r\\n   * @notice Hashes `DelegatedBatchWithGasPrice` message payload\\r\\n   * @param delegatedBatch struct\\r\\n   * @return hash\\r\\n   */\\r\\n  function hashDelegatedBatchWithGasPrice(\\r\\n    DelegatedBatchWithGasPrice memory delegatedBatch\\r\\n  )\\r\\n    public\\r\\n    view\\r\\n    returns (bytes32)\\r\\n  {\\r\\n    return _hashDelegatedBatchWithGasPrice(\\r\\n      delegatedBatch.account,\\r\\n      delegatedBatch.nonce,\\r\\n      delegatedBatch.to,\\r\\n      delegatedBatch.data,\\r\\n      delegatedBatch.gasPrice\\r\\n    );\\r\\n  }\\r\\n\\r\\n  // external functions (views)\\r\\n\\r\\n  /**\\r\\n   * @notice Gets next account nonce\\r\\n   * @param account account address\\r\\n   * @return next nonce\\r\\n   */\\r\\n  function getAccountNextNonce(\\r\\n    address account\\r\\n  )\\r\\n    external\\r\\n    view\\r\\n    returns (uint256)\\r\\n  {\\r\\n    return accountNonce[account].add(1);\\r\\n  }\\r\\n\\r\\n  // private functions\\r\\n\\r\\n  function _sendBatch(\\r\\n    address account,\\r\\n    address sender,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data\\r\\n  )\\r\\n    private\\r\\n  {\\r\\n    require(\\r\\n      account != address(0),\\r\\n      \\\"Gateway: cannot send from 0x0 account\\\"\\r\\n    );\\r\\n    require(\\r\\n      to.length > 0,\\r\\n      \\\"Gateway: cannot send empty batch\\\"\\r\\n    );\\r\\n    require(\\r\\n      data.length == to.length,\\r\\n      \\\"Gateway: invalid batch\\\"\\r\\n    );\\r\\n\\r\\n    if (account != sender) {\\r\\n      require(\\r\\n        personalAccountRegistry.verifyAccountOwner(account, sender) ||\\r\\n        externalAccountRegistry.verifyAccountOwner(account, sender),\\r\\n        \\\"Gateway: sender is not the account owner\\\"\\r\\n      );\\r\\n    }\\r\\n\\r\\n    bool succeeded;\\r\\n\\r\\n    for (uint256 i = 0; i < data.length; i++) {\\r\\n      require(\\r\\n        to[i] != address(0),\\r\\n        \\\"Gateway: cannot send to 0x0\\\"\\r\\n      );\\r\\n\\r\\n      // solhint-disable-next-line avoid-low-level-calls\\r\\n      (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender));\\r\\n\\r\\n      require(\\r\\n        succeeded,\\r\\n        \\\"Gateway: batch transaction reverted\\\"\\r\\n      );\\r\\n    }\\r\\n  }\\r\\n\\r\\n  // private functions (views)\\r\\n\\r\\n  function _hashDelegatedBatch(\\r\\n    address account,\\r\\n    uint256 nonce,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data\\r\\n  )\\r\\n    private\\r\\n    view\\r\\n    returns (bytes32)\\r\\n  {\\r\\n    return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked(\\r\\n      account,\\r\\n      nonce,\\r\\n      to,\\r\\n      _concatBytes(data)\\r\\n    ));\\r\\n  }\\r\\n\\r\\n  function _hashDelegatedBatchWithGasPrice(\\r\\n    address account,\\r\\n    uint256 nonce,\\r\\n    address[] memory to,\\r\\n    bytes[] memory data,\\r\\n    uint256 gasPrice\\r\\n  )\\r\\n    private\\r\\n    view\\r\\n    returns (bytes32)\\r\\n  {\\r\\n    return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked(\\r\\n      account,\\r\\n      nonce,\\r\\n      to,\\r\\n      _concatBytes(data),\\r\\n      gasPrice\\r\\n    ));\\r\\n  }\\r\\n\\r\\n// private functions (pure)\\r\\n\\r\\n  function _concatBytes(bytes[] memory data)\\r\\n    private\\r\\n    pure\\r\\n    returns (bytes memory)\\r\\n  {\\r\\n    bytes memory result;\\r\\n    uint dataLen = data.length;\\r\\n\\r\\n    for (uint i = 0 ; i < dataLen ; i++) {\\r\\n      result = abi.encodePacked(result, data[i]);\\r\\n    }\\r\\n\\r\\n    return result;\\r\\n  }\\r\\n}\\r\\n\",\"keccak256\":\"0x4e6d6d718916a6e3359505c569bb81ddae906c2f06701569b98ebf0278290d81\",\"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": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a",
  "devdoc": {
    "author": "Utkir Sobirov <sobirovutkir@gmail.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": {
      "addGuardian(address)": {
        "params": {
          "guardian": "guardian address"
        }
      },
      "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"
        }
      },
      "delegateBatchGuarded(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"
        }
      },
      "delegateBatchWithGasPriceGuarded(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"
        }
      },
      "delegateBatchesGuarded(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"
        }
      },
      "isGuardian(address)": {
        "params": {
          "guardian": "guardian address"
        },
        "returns": {
          "_0": "true when guardian exists"
        }
      },
      "isInitialized()": {
        "returns": {
          "_0": "true when contract is initialized"
        }
      },
      "removeGuardian(address)": {
        "params": {
          "guardian": "guardian address"
        }
      },
      "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"
        }
      },
      "sendBatchFromAccountGuarded(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"
        }
      },
      "sendBatchGuarded(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"
        }
      },
      "verifyGuardianSignature(bytes32,bytes)": {
        "params": {
          "messageHash": "message hash",
          "signature": "signature"
        },
        "returns": {
          "_0": "true on correct guardian signature"
        }
      }
    },
    "title": "Gateway V2 with guarded batching functions",
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "addGuardian(address)": {
        "notice": "Adds a new guardian"
      },
      "delegateBatch(address,uint256,address[],bytes[],bytes)": {
        "notice": "Delegates batch from the account"
      },
      "delegateBatchGuarded(address,uint256,address[],bytes[],bytes)": {
        "notice": "Delegates guarded batch from the account"
      },
      "delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)": {
        "notice": "Delegates batch from the account (with gas price)"
      },
      "delegateBatchWithGasPriceGuarded(address,uint256,address[],bytes[],bytes)": {
        "notice": "Delegates guarded batch from the account (with gas price)"
      },
      "delegateBatches(bytes[],bool)": {
        "notice": "Delegates multiple batches"
      },
      "delegateBatchesGuarded(bytes[],bool)": {
        "notice": "Delegates multiple guarded 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"
      },
      "isGuardian(address)": {
        "notice": "Check if guardian exists"
      },
      "isInitialized()": {
        "notice": "Check if contract is initialized"
      },
      "removeGuardian(address)": {
        "notice": "Removes the existing guardian"
      },
      "sendBatch(address[],bytes[])": {
        "notice": "Sends batch"
      },
      "sendBatchFromAccount(address,address[],bytes[])": {
        "notice": "Sends batch from the account"
      },
      "sendBatchFromAccountGuarded(address,address[],bytes[])": {
        "notice": "Sends guarded batch from the account"
      },
      "sendBatchGuarded(address[],bytes[])": {
        "notice": "Sends guarded batch"
      },
      "verifyGuardianSignature(bytes32,bytes)": {
        "notice": "Verifies guardian signature"
      }
    },
    "notice": "GSN replacement",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 1473,
        "contract": "src/gateway/GatewayV2.sol:GatewayV2",
        "label": "initializer",
        "offset": 0,
        "slot": "0",
        "type": "t_address"
      },
      {
        "astId": 1537,
        "contract": "src/gateway/GatewayV2.sol:GatewayV2",
        "label": "chainId",
        "offset": 0,
        "slot": "1",
        "type": "t_uint256"
      },
      {
        "astId": 40,
        "contract": "src/gateway/GatewayV2.sol:GatewayV2",
        "label": "guardians",
        "offset": 0,
        "slot": "2",
        "type": "t_mapping(t_address,t_bool)"
      },
      {
        "astId": 5010,
        "contract": "src/gateway/GatewayV2.sol:GatewayV2",
        "label": "externalAccountRegistry",
        "offset": 0,
        "slot": "3",
        "type": "t_contract(ExternalAccountRegistry)4193"
      },
      {
        "astId": 5012,
        "contract": "src/gateway/GatewayV2.sol:GatewayV2",
        "label": "personalAccountRegistry",
        "offset": 0,
        "slot": "4",
        "type": "t_contract(PersonalAccountRegistry)7735"
      },
      {
        "astId": 5016,
        "contract": "src/gateway/GatewayV2.sol:GatewayV2",
        "label": "accountNonce",
        "offset": 0,
        "slot": "5",
        "type": "t_mapping(t_address,t_uint256)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_contract(ExternalAccountRegistry)4193": {
        "encoding": "inplace",
        "label": "contract ExternalAccountRegistry",
        "numberOfBytes": "20"
      },
      "t_contract(PersonalAccountRegistry)7735": {
        "encoding": "inplace",
        "label": "contract PersonalAccountRegistry",
        "numberOfBytes": "20"
      },
      "t_mapping(t_address,t_bool)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => bool)",
        "numberOfBytes": "32",
        "value": "t_bool"
      },
      "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"
      }
    }
  }
}