diff --git a/DEPLOYMENTS.md b/DEPLOYMENTS.md index 22b8fe5b..94e76a6e 100644 --- a/DEPLOYMENTS.md +++ b/DEPLOYMENTS.md @@ -36,12 +36,14 @@ | `BalancesHelperV2` | `ropsten` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://ropsten.etherscan.io/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0x85a9b1e970b917b4af56111429d9424409e0527fec62079e6451a94de7a5c737](https://ropsten.etherscan.io/tx/0x85a9b1e970b917b4af56111429d9424409e0527fec62079e6451a94de7a5c737) | | `BalancesHelperV2` | `goerli` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://goerli.etherscan.io/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0x730049031e4acf1595d7c01d6184b9fb1c6a2855753cd4b765f856a0da9fa6eb](https://goerli.etherscan.io/tx/0x730049031e4acf1595d7c01d6184b9fb1c6a2855753cd4b765f856a0da9fa6eb) | | `BalancesHelperV2` | `xdai` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://blockscout.com/poa/xdai/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0xaf526ad2091fb9fc3c64c04b23ed38580c8e23195c9a5c56956396e425d95fec](https://blockscout.com/poa/xdai/tx/0xaf526ad2091fb9fc3c64c04b23ed38580c8e23195c9a5c56956396e425d95fec) | +| `BalancesHelperV2` | `sokol` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://blockscout.com/poa/sokol/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0x3c525b35e3571587d7b03d7c24a687a3b99a76a81e6ea76516c5d54c0b88349b](https://blockscout.com/poa/sokol/tx/0x3c525b35e3571587d7b03d7c24a687a3b99a76a81e6ea76516c5d54c0b88349b) | | `BalancesHelperV2` | `bsc` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://bscscan.com/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0xa2074dd7aa22eb02ef1357daee07b09518a421b11d49c65b8c5b29605e769ed8](https://bscscan.com/tx/0xa2074dd7aa22eb02ef1357daee07b09518a421b11d49c65b8c5b29605e769ed8) | | `BalancesHelperV2` | `fantom` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://ftmscan.com/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0x42ddbc5b0c33282438089ab5876a35358ab55571ece08a1ac4a8186eec650677](https://ftmscan.com/tx/0x42ddbc5b0c33282438089ab5876a35358ab55571ece08a1ac4a8186eec650677) | | `BalancesHelperV2` | `fantomTest` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://explorer.testnet.fantom.network/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0xcf785451e31308e606ccbb64338bb31ca0d21dd14dee921d36778cbbe190fff5](https://explorer.testnet.fantom.network/transactions/0xcf785451e31308e606ccbb64338bb31ca0d21dd14dee921d36778cbbe190fff5) | | `BalancesHelperV2` | `matic` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://polygonscan.com/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0x67dfa193a4d9425d9e8fd23030c11d5a77cab3f86bb0bb58c57c7b8728cb611a](https://polygonscan.com/tx/0x67dfa193a4d9425d9e8fd23030c11d5a77cab3f86bb0bb58c57c7b8728cb611a) | | `BalancesHelperV2` | `mumbai` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://mumbai.polygonscan.com/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0x4ac32927cd25414eefdaa64fbdb217a9b9aac98105283cfe7d259635ce7de87a](https://mumbai.polygonscan.com/tx/0x4ac32927cd25414eefdaa64fbdb217a9b9aac98105283cfe7d259635ce7de87a) | | `BalancesHelperV2` | `avalanche` | [0x13261B2b8674Cb855c408F3721281330ee16C66E](https://snowtrace.io/address/0x13261B2b8674Cb855c408F3721281330ee16C66E) | [0x3e0f88326aad61f07006016d497b4ae8c80f17ca17b1407ab928127bc3f6b06d](https://snowtrace.io/tx/0x3e0f88326aad61f07006016d497b4ae8c80f17ca17b1407ab928127bc3f6b06d) | +| `BalancesHelperV2` | `fuji` | [0x13261B2b8674Cb855c408F3721281330ee16C66E](https://testnet.snowtrace.io/address/0x13261B2b8674Cb855c408F3721281330ee16C66E) | [0xc68d2e1d7e9921a4bcb5e02ac326ad5dd2c6ed1030c4ba1e2994fd0a63cf9742](https://testnet.snowtrace.io/tx/0xc68d2e1d7e9921a4bcb5e02ac326ad5dd2c6ed1030c4ba1e2994fd0a63cf9742) | | `BalancesHelperV2` | `aurora` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0x5ab4c1067308ff7ddac1f9e3db39ed42dadf2d1a3d2dd9337c80060b7798772d | | `BalancesHelperV2` | `auroraTest` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0xcbbf436ff90d4351e8409846374d3be44b625fd55601e8adebf392db7056f9f5 | | `BalancesHelperV2` | `arbitrum` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0x79d8b685ddc42564227581bdf9f53cd44f8ca3fb2a97187ed1c43c831b091d0f | @@ -261,6 +263,12 @@ | `Gateway` | `arbitrumNova` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0x79ff0dafd337c73d39c67bd8333fc6524df7690c879f8796789cb58f20c19f4a | | `Gateway` | `arbitrumNitro` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0x36f8325ad8033f74aaf44f3b83a5793928723d9af70eac918eaa8a288d1ab3e5 | | `Gateway` | `etherspot` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0xba898531d95380c97307201fb1fe773801fb83343d9096c6bc4380402ed4486b | +| `GatewayV2` | `goerli` | [0xBEd52610518788B931f7825301909e7616273d47](https://goerli.etherscan.io/address/0xBEd52610518788B931f7825301909e7616273d47) | [0x5d1526546b15cc9c23dfdda9c05c66db27468bcdf75f3dbc3ce43d63670e96d8](https://goerli.etherscan.io/tx/0x5d1526546b15cc9c23dfdda9c05c66db27468bcdf75f3dbc3ce43d63670e96d8) | +| `GatewayV2` | `sokol` | [0xBEd52610518788B931f7825301909e7616273d47](https://blockscout.com/poa/sokol/address/0xBEd52610518788B931f7825301909e7616273d47) | [0xc39568a814d9b8e6137049bc34403b6940bdec03545f304778558ff1444ee393](https://blockscout.com/poa/sokol/tx/0xc39568a814d9b8e6137049bc34403b6940bdec03545f304778558ff1444ee393) | +| `GatewayV2` | `bscTest` | [0xBEd52610518788B931f7825301909e7616273d47](https://testnet.bscscan.com/address/0xBEd52610518788B931f7825301909e7616273d47) | [0xd56fecb8c5a6ce335048541beffab457e5e7681958270321da8fe51c34e934bf](https://testnet.bscscan.com/tx/0xd56fecb8c5a6ce335048541beffab457e5e7681958270321da8fe51c34e934bf) | +| `GatewayV2` | `fantomTest` | [0xBEd52610518788B931f7825301909e7616273d47](https://explorer.testnet.fantom.network/address/0xBEd52610518788B931f7825301909e7616273d47) | [0xcce8ae16dd3a0eff4e5748005473002ebb2e0a758c02524290e52d85cf91652a](https://explorer.testnet.fantom.network/transactions/0xcce8ae16dd3a0eff4e5748005473002ebb2e0a758c02524290e52d85cf91652a) | +| `GatewayV2` | `fuji` | [0x9FC4DdE698E5cf1Ee8d6e2D25c835836d9af1C8F](https://testnet.snowtrace.io/address/0x9FC4DdE698E5cf1Ee8d6e2D25c835836d9af1C8F) | [0x8db8b0e7e1e833d4b9ef812bf06fb7338ac25b496447512b5677436a4640a8d0](https://testnet.snowtrace.io/tx/0x8db8b0e7e1e833d4b9ef812bf06fb7338ac25b496447512b5677436a4640a8d0) | +| `GatewayV2` | `arbitrumTest` | 0xBEd52610518788B931f7825301909e7616273d47 | 0x12a452e4cf52ed74b5c7baab0581cc622661636c1f0b12be016b85765395af4a | | `HopFacet` | `goerli` | [0x9B950aa30575F3d1E33bd0b2DD0AF4DE496F39F5](https://goerli.etherscan.io/address/0x9B950aa30575F3d1E33bd0b2DD0AF4DE496F39F5) | [0xfda9425406016686c3ce58061d202827338ee9de02e0974e5e1af7ec845824b2](https://goerli.etherscan.io/tx/0xfda9425406016686c3ce58061d202827338ee9de02e0974e5e1af7ec845824b2) | | `HopFacet` | `kovan` | [0x9B950aa30575F3d1E33bd0b2DD0AF4DE496F39F5](https://kovan.etherscan.io/address/0x9B950aa30575F3d1E33bd0b2DD0AF4DE496F39F5) | [0xdaaecd03b1addd1eb80ee80ae6fce9795442363add8e46be678aa9ffdfe68858](https://kovan.etherscan.io/tx/0xdaaecd03b1addd1eb80ee80ae6fce9795442363add8e46be678aa9ffdfe68858) | | `HopFacet` | `mumbai` | [0x9B950aa30575F3d1E33bd0b2DD0AF4DE496F39F5](https://mumbai.polygonscan.com/address/0x9B950aa30575F3d1E33bd0b2DD0AF4DE496F39F5) | [0x21ea4c33e53d8519650936022f26f0968a6ed1f944b89b202e8ba179be2c1989](https://mumbai.polygonscan.com/tx/0x21ea4c33e53d8519650936022f26f0968a6ed1f944b89b202e8ba179be2c1989) | diff --git a/artifacts/GatewayV2.json b/artifacts/GatewayV2.json new file mode 100644 index 00000000..238b1b6c --- /dev/null +++ b/artifacts/GatewayV2.json @@ -0,0 +1,587 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GatewayV2", + "sourceName": "src/gateway/GatewayV2.sol", + "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" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/artifacts/console.json b/artifacts/console.json new file mode 100644 index 00000000..3e33d764 --- /dev/null +++ b/artifacts/console.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "console", + "sourceName": "hardhat/console.sol", + "abi": [], + "bytecode": "0x602d6050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/deploy/008_create-gateway-v2.ts b/deploy/008_create-gateway-v2.ts new file mode 100644 index 00000000..d669664f --- /dev/null +++ b/deploy/008_create-gateway-v2.ts @@ -0,0 +1,18 @@ +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async hre => { + const { + deployments: { deploy }, + getNamedAccounts, + } = hre; + const { from } = await getNamedAccounts(); + + await deploy('GatewayV2', { + from, + log: true, + }); +}; + +func.tags = ['create', 'gateway-v2']; + +module.exports = func; diff --git a/deploy/108_setup-gateway-v2.ts b/deploy/108_setup-gateway-v2.ts new file mode 100644 index 00000000..7c410820 --- /dev/null +++ b/deploy/108_setup-gateway-v2.ts @@ -0,0 +1,31 @@ +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async hre => { + const { + deployments: { get, log, execute, read }, + getNamedAccounts, + } = hre; + const { from } = await getNamedAccounts(); + + if (await read('GatewayV2', 'isInitialized')) { + log('GatewayV2 already initialized'); + } else { + const externalAccountRegistry = await get('ExternalAccountRegistry'); + const personalAccountRegistry = await get('PersonalAccountRegistry'); + + await execute( + 'GatewayV2', + { + from, + log: true, + }, + 'initialize', + externalAccountRegistry.address, + personalAccountRegistry.address, + ); + } +}; + +func.tags = ['setup', 'gateway-v2']; + +module.exports = func; diff --git a/deployments/arbitrumTest/BalancesHelperV2.json b/deployments/arbitrumTest/BalancesHelperV2.json new file mode 100644 index 00000000..9d05ac9b --- /dev/null +++ b/deployments/arbitrumTest/BalancesHelperV2.json @@ -0,0 +1,144 @@ +{ + "address": "0xe5A160F89f330cc933816E896a3F36376DE0a835", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "AccountZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getBalances", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getSuperfluidWrappedTokenBalances", + "outputs": [ + { + "internalType": "int256[]", + "name": "", + "type": "int256[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "args": [], + "solcInputHash": "893c7c8579088197a1acbd2718e7b759", + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"AccountZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getSuperfluidWrappedTokenBalances\",\"outputs\":[{\"internalType\":\"int256[]\",\"name\":\"\",\"type\":\"int256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"AccountZeroAddress(address,address)\":[{\"notice\":\"Custom errors to handle address(0)\"}]},\"kind\":\"user\",\"methods\":{\"getBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple ERC20 tokens.\"},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple Wrapped Super Tokens.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/common/helpers/BalancesHelperV2.sol\":\"BalancesHelperV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0x6ebf1944ab804b8660eb6fc52f9fe84588cee01c2566a69023e59497e7d27f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperAgreement.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperfluidToken } from \\\"./ISuperfluidToken.sol\\\";\\n\\n/**\\n * @title Super agreement interface\\n * @author Superfluid\\n */\\ninterface ISuperAgreement {\\n\\n /**\\n * @dev Get the type of the agreement class\\n */\\n function agreementType() external view returns (bytes32);\\n\\n /**\\n * @dev Calculate the real-time balance for the account of this agreement class\\n * @param account Account the state belongs to\\n * @param time Time used for the calculation\\n * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement\\n * @return deposit Account deposit amount of this agreement\\n * @return owedDeposit Account owed deposit amount of this agreement\\n */\\n function realtimeBalanceOf(\\n ISuperfluidToken token,\\n address account,\\n uint256 time\\n )\\n external\\n view\\n returns (\\n int256 dynamicBalance,\\n uint256 deposit,\\n uint256 owedDeposit\\n );\\n\\n}\\n\",\"keccak256\":\"0xc3a6a907245116bcecc70fe4b207454012e8ce4fa190228fb8bbe39e0b1bc5cf\",\"license\":\"AGPLv3\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperAgreement } from \\\"./ISuperAgreement.sol\\\";\\n\\n\\n/**\\n * @title Superfluid token interface\\n * @author Superfluid\\n */\\ninterface ISuperfluidToken {\\n\\n /**************************************************************************\\n * Basic information\\n *************************************************************************/\\n\\n /**\\n * @dev Get superfluid host contract address\\n */\\n function getHost() external view returns(address host);\\n\\n /**\\n * @dev Encoded liquidation type data mainly used for handling stack to deep errors\\n *\\n * Note:\\n * - version: 1\\n * - liquidationType key:\\n * - 0 = reward account receives reward (PIC period)\\n * - 1 = liquidator account receives reward (Pleb period)\\n * - 2 = liquidator account receives reward (Pirate period/bailout)\\n */\\n struct LiquidationTypeData {\\n uint256 version;\\n uint8 liquidationType;\\n }\\n\\n /**************************************************************************\\n * Real-time balance functions\\n *************************************************************************/\\n\\n /**\\n * @dev Calculate the real balance of a user, taking in consideration all agreements of the account\\n * @param account for the query\\n * @param timestamp Time of balance\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOf(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit);\\n\\n /**\\n * @notice Calculate the realtime balance given the current host.getNow() value\\n * @dev realtimeBalanceOf with timestamp equals to block timestamp\\n * @param account for the query\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOfNow(\\n address account\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit,\\n uint256 timestamp);\\n\\n /**\\n * @notice Check if account is critical\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is critical (should use future)\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCritical(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is critical now (current host.getNow())\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCriticalNow(\\n address account\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is solvent\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is solvent (should use future)\\n * @return isSolvent\\n */\\n function isAccountSolvent(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Check if account is solvent now\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @return isSolvent\\n */\\n function isAccountSolventNow(\\n address account\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Get a list of agreements that is active for the account\\n * @dev An active agreement is one that has state for the account\\n * @param account Account to query\\n * @return activeAgreements List of accounts that have non-zero states for the account\\n */\\n function getAccountActiveAgreements(address account)\\n external view\\n returns(ISuperAgreement[] memory activeAgreements);\\n\\n\\n /**************************************************************************\\n * Super Agreement hosting functions\\n *************************************************************************/\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function createAgreement(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement created event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementCreated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Get data of the agreement\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @return data Data of the agreement\\n */\\n function getAgreementData(\\n address agreementClass,\\n bytes32 id,\\n uint dataLength\\n )\\n external view\\n returns(bytes32[] memory data);\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function updateAgreementData(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement updated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementUpdated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Close the agreement\\n * @param id Agreement ID\\n */\\n function terminateAgreement(\\n bytes32 id,\\n uint dataLength\\n )\\n external;\\n /**\\n * @dev Agreement terminated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n */\\n event AgreementTerminated(\\n address indexed agreementClass,\\n bytes32 id\\n );\\n\\n /**\\n * @dev Update agreement state slot\\n * @param account Account to be updated\\n *\\n * NOTE\\n * - To clear the storage out, provide zero-ed array of intended length\\n */\\n function updateAgreementStateSlot(\\n address account,\\n uint256 slotId,\\n bytes32[] calldata slotData\\n )\\n external;\\n /**\\n * @dev Agreement account state updated event\\n * @param agreementClass Contract address of the agreement\\n * @param account Account updated\\n * @param slotId slot id of the agreement state\\n */\\n event AgreementStateUpdated(\\n address indexed agreementClass,\\n address indexed account,\\n uint256 slotId\\n );\\n\\n /**\\n * @dev Get data of the slot of the state of an agreement\\n * @param agreementClass Contract address of the agreement\\n * @param account Account to query\\n * @param slotId slot id of the state\\n * @param dataLength length of the state data\\n */\\n function getAgreementStateSlot(\\n address agreementClass,\\n address account,\\n uint256 slotId,\\n uint dataLength\\n )\\n external view\\n returns (bytes32[] memory slotData);\\n\\n /**\\n * @notice Settle balance from an account by the agreement\\n * @dev The agreement needs to make sure that the balance delta is balanced afterwards\\n * @param account Account to query.\\n * @param delta Amount of balance delta to be settled\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function settleBalance(\\n address account,\\n int256 delta\\n )\\n external;\\n\\n /**\\n * @dev Make liquidation payouts (v2)\\n * @param id Agreement ID\\n * @param liquidationTypeData Data regarding the version of the liquidation schema and the type\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount\\n * @param targetAccount Account of the stream sender\\n * @param rewardAmount The amount the reward recepient account will receive\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n *\\n * - If a bailout is required (bailoutAmount > 0)\\n * - the actual reward (single deposit) goes to the executor,\\n * - while the reward account becomes the bailout account\\n * - total bailout include: bailout amount + reward amount\\n * - the targetAccount will be bailed out\\n * - If a bailout is not required\\n * - the targetAccount will pay the rewardAmount\\n * - the liquidator (reward account in PIC period) will receive the rewardAmount\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function makeLiquidationPayoutsV2\\n (\\n bytes32 id,\\n bytes memory liquidationTypeData,\\n address liquidatorAccount,\\n bool useDefaultRewardAccount,\\n address targetAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta\\n ) external;\\n /**\\n * @dev Agreement liquidation event v2 (including agent account)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param targetAccount Account of the stream sender\\n * @param rewardAccount Account that collects the reward or bails out insolvent accounts\\n * @param rewardAmount The amount the reward recipient account balance should change by\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n * @param liquidationTypeData The encoded liquidation type data including the version (how to decode)\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if the agreement is liquidated during the PIC period\\n * - the rewardAccount will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount\\n * - the targetAccount will pay for the rewardAmount\\n * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent\\n * - the liquidatorAccount will get the rewardAmount (remaining deposit)\\n * - the targetAccount will pay for the rewardAmount\\n * - if the targetAccount is insolvent\\n * - the liquidatorAccount will get the rewardAmount (single deposit)\\n * - the rewardAccount will pay for both the rewardAmount and bailoutAmount\\n * - the targetAccount will receive the bailoutAmount\\n */\\n event AgreementLiquidatedV2(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed liquidatorAccount,\\n address indexed targetAccount,\\n address rewardAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta,\\n bytes liquidationTypeData\\n );\\n\\n /**************************************************************************\\n * Function modifiers for access control and parameter validations\\n *\\n * While they cannot be explicitly stated in function definitions, they are\\n * listed in function definition comments instead for clarity.\\n *\\n * NOTE: solidity-coverage not supporting it\\n *************************************************************************/\\n\\n /// @dev The msg.sender must be host contract\\n //modifier onlyHost() virtual;\\n\\n /// @dev The msg.sender must be a listed agreement.\\n //modifier onlyAgreement() virtual;\\n\\n /**************************************************************************\\n * DEPRECATED\\n *************************************************************************/\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param rewardAccount Account that collect the reward\\n * @param rewardAmount Amount of liquidation reward\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event AgreementLiquidated(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed rewardAccount,\\n uint256 rewardAmount\\n );\\n\\n /**\\n * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy)\\n * @param bailoutAccount Account that bailout the penalty account\\n * @param bailoutAmount Amount of account bailout\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event Bailout(\\n address indexed bailoutAccount,\\n uint256 bailoutAmount\\n );\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2)\\n * @param liquidatorAccount Account of the agent that performed the liquidation.\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param bondAccount Account that collect the reward or bailout accounts\\n * @param rewardAmount Amount of liquidation reward\\n * @param bailoutAmount Amount of liquidation bailouot\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if bailout is equal to 0, then\\n * - the bondAccount will get the rewardAmount,\\n * - the penaltyAccount will pay for the rewardAmount.\\n * - if bailout is larger than 0, then\\n * - the liquidatorAccount will get the rewardAmouont,\\n * - the bondAccount will pay for both the rewardAmount and bailoutAmount,\\n * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.\\n */\\n event AgreementLiquidatedBy(\\n address liquidatorAccount,\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed bondAccount,\\n uint256 rewardAmount,\\n uint256 bailoutAmount\\n );\\n}\\n\",\"keccak256\":\"0x9189eaba9e856cc4932ea29eeaf4e89a09448dde13860591691ec122856fdc75\",\"license\":\"AGPLv3\"},\"src/common/helpers/BalancesHelperV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\n// solhint-disable-next-line\\r\\npragma solidity 0.8.4;\\r\\n\\r\\n/// @title BalancesHelperV2\\r\\n/// @author Luke Wickens \\r\\n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\\r\\n\\r\\nimport {ISuperfluidToken} from \\\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\\\";\\r\\nimport {IERC20} from \\\"@openzeppelin/contracts/interfaces/IERC20.sol\\\";\\r\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\r\\n\\r\\ncontract BalancesHelperV2 {\\r\\n using Address for address;\\r\\n\\r\\n /// @notice Custom errors to handle address(0)\\r\\n error AccountZeroAddress(address account, address token);\\r\\n error TokenZeroAddress(address account, address token);\\r\\n\\r\\n constructor() {}\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple ERC20 tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getBalances(address[] calldata accounts, address[] calldata tokens)\\r\\n external\\r\\n view\\r\\n returns (uint256[] memory)\\r\\n {\\r\\n uint256[] memory result = new uint256[](\\r\\n accounts.length * tokens.length\\r\\n );\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getBalance(accounts[i], tokens[j]);\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getSuperfluidWrappedTokenBalances(\\r\\n address[] calldata accounts,\\r\\n address[] calldata tokens\\r\\n ) external view returns (int256[] memory) {\\r\\n int256[] memory result = new int256[](accounts.length * tokens.length);\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getSuperfluidWrappedTokenBalance(\\r\\n accounts[i],\\r\\n tokens[j]\\r\\n );\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// Private fuctions\\r\\n\\r\\n /// @notice Returns balance of account for an ERC20 token.\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return balance of account as uint256.\\r\\n\\r\\n function _getBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (uint256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\\r\\n );\\r\\n\\r\\n return abi.decode(returnedData, (uint256));\\r\\n }\\r\\n\\r\\n /// @notice Returns real balance of a user, taking into consideration all agreements of account\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return available balance of account as int256.\\r\\n\\r\\n function _getSuperfluidWrappedTokenBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (int256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(\\r\\n ISuperfluidToken(token).realtimeBalanceOfNow.selector,\\r\\n account\\r\\n )\\r\\n );\\r\\n\\r\\n (int256 availableBalance, , , ) = abi.decode(\\r\\n returnedData,\\r\\n (int256, uint256, uint256, uint256)\\r\\n );\\r\\n return availableBalance;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xee88323570149a5d9e569da056eaa089cf4baacfb3713a0dd282090b1d0847d2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061108a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "devdoc": { + "kind": "dev", + "methods": { + "getBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "AccountZeroAddress(address,address)": [ + { + "notice": "Custom errors to handle address(0)" + } + ] + }, + "kind": "user", + "methods": { + "getBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple ERC20 tokens." + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple Wrapped Super Tokens." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumTest/GatewayV2.json b/deployments/arbitrumTest/GatewayV2.json new file mode 100644 index 00000000..9da75b91 --- /dev/null +++ b/deployments/arbitrumTest/GatewayV2.json @@ -0,0 +1,926 @@ +{ + "address": "0xBEd52610518788B931f7825301909e7616273d47", + "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": "0x12a452e4cf52ed74b5c7baab0581cc622661636c1f0b12be016b85765395af4a", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "contractAddress": null, + "transactionIndex": 1, + "gasUsed": "2822044", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe84e681c90a6573f698b3c5fdca8aa2a0204ce013e46fbf9c10f4405e8b803b8", + "transactionHash": "0x12a452e4cf52ed74b5c7baab0581cc622661636c1f0b12be016b85765395af4a", + "logs": [], + "blockNumber": 16706197, + "cumulativeGasUsed": "2822044", + "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 \",\"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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 ", + "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" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json b/deployments/arbitrumTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json new file mode 100644 index 00000000..fa380d29 --- /dev/null +++ b/deployments/arbitrumTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json @@ -0,0 +1,142 @@ +{ + "language": "Solidity", + "sources": { + "src/payments/PaymentRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./PaymentDepositAccount.sol\";\n\n\n/**\n * @title Payment registry\n *\n * @notice A registry for payment and payment channels\n *\n * @dev the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message.\n * Process will be rejected when any of senders channels will be committed.\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct Deposit {\n address account;\n mapping(address => uint256) withdrawnAmount;\n mapping(address => uint256) exitLockedUntil;\n }\n\n struct PaymentChannel {\n uint256 committedAmount;\n }\n\n struct DepositWithdrawal {\n address owner;\n address token;\n uint256 amount;\n }\n\n struct PaymentChannelCommit {\n address sender;\n address recipient;\n address token;\n bytes32 uid;\n uint256 blockNumber;\n uint256 amount;\n }\n\n uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;\n\n bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(\n \"DepositWithdrawal(address owner,address token,uint256 amount)\"\n );\n bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(\n \"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n uint256 public depositExitLockPeriod;\n\n mapping(address => Deposit) private deposits;\n mapping(bytes32 => PaymentChannel) private paymentChannels;\n\n // events\n\n /**\n * @dev Emitted when the deposit account is deployed\n * @param depositAccount deposit account address\n * @param owner owner address\n */\n event DepositAccountDeployed(\n address depositAccount,\n address owner\n );\n\n /**\n * @dev Emitted when the deposit exist is requested\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param lockedUntil deposit exist locked util time\n */\n event DepositExitRequested(\n address depositAccount,\n address owner,\n address token,\n uint256 lockedUntil\n );\n\n /**\n * @dev Emitted when the deposit exist is completed\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount deposit exist amount\n */\n event DepositExitCompleted(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the deposit exist is rejected\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n */\n event DepositExitRejected(\n address depositAccount,\n address owner,\n address token\n );\n\n /**\n * @dev Emitted when the deposit has been withdrawn\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount withdrawn amount\n */\n event DepositWithdrawn(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment channel has been committed\n * @param hash channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @param amount committed amount\n */\n event PaymentChannelCommitted(\n bytes32 hash,\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentWithdrawn(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been deposited\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentDeposited(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn and deposited (split)\n * @param channelHash channel hash\n * @param totalValue payment total value\n * @param depositValue payment deposited value\n */\n event PaymentSplit(\n bytes32 channelHash,\n uint256 totalValue,\n uint256 depositValue\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initialize `PaymentRegistry` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n * @param depositExitLockPeriod_ deposit exit lock period\n * @param guardians_ array of guardians addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_,\n uint256 depositExitLockPeriod_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n if (depositExitLockPeriod_ == 0) {\n depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;\n } else {\n depositExitLockPeriod = depositExitLockPeriod_;\n }\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Deploys deposit account\n * @param owner owner address\n */\n function deployDepositAccount(\n address owner\n )\n external\n {\n _deployDepositAccount(owner);\n }\n\n /**\n * @notice Requests deposit exit\n * @param token token address\n */\n function requestDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil == 0,\n \"PaymentRegistry: deposit exit already requested\"\n );\n\n _deployDepositAccount(owner);\n\n // solhint-disable-next-line not-rely-on-time\n lockedUntil = now.add(depositExitLockPeriod);\n\n deposits[owner].exitLockedUntil[token] = lockedUntil;\n\n emit DepositExitRequested(\n deposits[owner].account,\n owner,\n token,\n lockedUntil\n );\n }\n\n /**\n * @notice Processes deposit exit\n * @param token token address\n */\n function processDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil != 0,\n \"PaymentRegistry: deposit exit not requested\"\n );\n\n require(\n // solhint-disable-next-line not-rely-on-time\n lockedUntil <= now,\n \"PaymentRegistry: deposit exit locked\"\n );\n\n deposits[owner].exitLockedUntil[token] = 0;\n\n address depositAccount = deposits[owner].account;\n uint256 depositValue;\n\n if (token == address(0)) {\n depositValue = depositAccount.balance;\n } else {\n depositValue = ERC20Token(token).balanceOf(depositAccount);\n }\n\n _transferFromDeposit(\n depositAccount,\n owner,\n token,\n depositValue\n );\n\n emit DepositExitCompleted(\n depositAccount,\n owner,\n token,\n depositValue\n );\n }\n\n /**\n * @notice Withdraws deposit\n * @param token token address\n * @param amount amount to withdraw\n * @param guardianSignature guardian signature\n */\n function withdrawDeposit(\n address token,\n uint256 amount,\n bytes calldata guardianSignature\n )\n external\n {\n address owner = _getContextAccount();\n uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);\n\n require(\n value > 0,\n \"PaymentRegistry: invalid amount\"\n );\n\n bytes32 messageHash = _hashDepositWithdrawal(\n owner,\n token,\n amount\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n deposits[owner].withdrawnAmount[token] = amount;\n\n _verifyDepositExitOrDeployAccount(owner, token);\n\n _transferFromDeposit(\n deposits[owner].account,\n owner,\n token,\n value\n );\n\n emit DepositWithdrawn(\n deposits[owner].account,\n owner,\n token,\n amount\n );\n }\n\n /**\n * @notice Commits payment channel and withdraw payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndWithdraw(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue\n );\n\n emit PaymentWithdrawn(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel and deposit payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndDeposit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(recipient),\n token,\n paymentValue\n );\n\n emit PaymentDeposited(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel, withdraws and deposits (split) payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param depositPaymentValue amount to deposit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndSplit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n uint256 depositPaymentValue,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferSplitFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue,\n depositPaymentValue\n );\n\n emit PaymentSplit(hash, paymentValue, depositPaymentValue);\n }\n\n // external functions (views)\n\n /**\n * @notice Computes deposit account address\n * @param owner owner address\n * @return deposit account address\n */\n function computeDepositAccountAddress(\n address owner\n )\n external\n view\n returns (address)\n {\n return _computeDepositAccountAddress(owner);\n }\n\n /**\n * @notice Checks if deposit account is deployed\n * @param owner owner address\n * @return true when deposit account is deployed\n */\n function isDepositAccountDeployed(\n address owner\n )\n external\n view\n returns (bool)\n {\n return deposits[owner].account != address(0);\n }\n\n /**\n * @notice Gets deposit exit locked until time\n * @param owner owner address\n * @param token token address\n * @return locked until time\n */\n function getDepositExitLockedUntil(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].exitLockedUntil[token];\n }\n\n /**\n * @notice Gets deposit withdrawn amount\n * @param owner owner address\n * @param token token address\n * @return withdrawn amount\n */\n function getDepositWithdrawnAmount(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].withdrawnAmount[token];\n }\n\n /**\n * @notice Gets payment channel committed amount\n * @param hash payment channel hash\n * @return committed amount\n */\n function getPaymentChannelCommittedAmount(\n bytes32 hash\n )\n external\n view\n returns (uint256)\n {\n return paymentChannels[hash].committedAmount;\n }\n\n // external functions (pure)\n\n /**\n * @notice Computes payment channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @return hash\n */\n function computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n external\n pure\n returns (bytes32)\n {\n return _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DepositWithdrawal` message payload\n * @param depositWithdrawal struct\n * @return hash\n */\n function hashDepositWithdrawal(\n DepositWithdrawal memory depositWithdrawal\n )\n public\n view\n returns (bytes32)\n {\n return _hashDepositWithdrawal(\n depositWithdrawal.owner,\n depositWithdrawal.token,\n depositWithdrawal.amount\n );\n }\n\n /**\n * @notice Hashes `PaymentChannelCommit` message payload\n * @param paymentChannelCommit struct\n * @return hash\n */\n function hashPaymentChannelCommit(\n PaymentChannelCommit memory paymentChannelCommit\n )\n public\n view\n returns (bytes32)\n {\n return _hashPaymentChannelCommit(\n paymentChannelCommit.sender,\n paymentChannelCommit.recipient,\n paymentChannelCommit.token,\n paymentChannelCommit.uid,\n paymentChannelCommit.blockNumber,\n paymentChannelCommit.amount\n );\n }\n\n // private functions\n\n function _deployDepositAccount(\n address owner\n )\n private\n {\n if (deposits[owner].account == address(0)) {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());\n\n emit DepositAccountDeployed(\n deposits[owner].account,\n owner\n );\n }\n }\n\n function _verifyDepositExitOrDeployAccount(\n address owner,\n address token\n )\n private\n {\n if (deposits[owner].exitLockedUntil[token] > 0) {\n deposits[owner].exitLockedUntil[token] = 0;\n\n emit DepositExitRejected(\n deposits[owner].account,\n owner,\n token\n );\n } else {\n _deployDepositAccount(owner);\n }\n }\n\n function _commitPaymentChannel(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes memory senderSignature,\n bytes memory guardianSignature\n )\n private\n returns (bytes32 hash, address depositAccount, uint256 paymentValue)\n {\n bytes32 messageHash = _hashPaymentChannelCommit(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n );\n\n if (senderSignature.length == 0) {\n require(\n externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),\n \"PaymentRegistry: invalid guardian signature\"\n );\n } else {\n address signer = messageHash.recoverAddress(senderSignature);\n\n if (sender != signer) {\n require(\n personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||\n externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),\n \"PaymentRegistry: invalid sender signature\"\n );\n }\n }\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n hash = _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n\n /// @dev calc payment value\n paymentValue = amount.sub(paymentChannels[hash].committedAmount);\n\n require(\n paymentValue != 0,\n \"PaymentRegistry: invalid payment value\"\n );\n\n paymentChannels[hash].committedAmount = amount;\n\n _verifyDepositExitOrDeployAccount(sender, token);\n\n depositAccount = deposits[sender].account;\n\n emit PaymentChannelCommitted(\n hash,\n sender,\n recipient,\n token,\n uid,\n amount\n );\n\n return (hash, depositAccount, paymentValue);\n }\n\n function _transferFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 value\n )\n private\n {\n if (token == address(0)) {\n PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n to,\n value,\n new bytes(0)\n );\n } else {\n bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n token,\n 0,\n abi.encodeWithSelector(\n ERC20Token(token).transfer.selector,\n to,\n value\n )\n );\n\n if (response.length > 0) {\n require(\n abi.decode(response, (bool)),\n \"PaymentRegistry: ERC20Token transfer reverted\"\n );\n }\n }\n }\n\n function _transferSplitFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 paymentValue,\n uint256 depositValue\n )\n private\n {\n require(\n depositValue > 0,\n \"PaymentRegistry: invalid deposit value\"\n );\n\n uint256 withdrawValue = paymentValue.sub(depositValue);\n\n require(\n withdrawValue > 0,\n \"PaymentRegistry: invalid withdraw value\"\n );\n\n _transferFromDeposit(\n depositAccount,\n to,\n token,\n withdrawValue\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(to),\n token,\n depositValue\n );\n }\n\n // private functions (views)\n\n function _computeDepositAccountAddress(\n address owner\n )\n private\n view\n returns (address)\n {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n bytes memory creationCode = type(PaymentDepositAccount).creationCode;\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 function _hashDepositWithdrawal(\n address owner,\n address token,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(\n owner,\n token,\n amount\n ));\n }\n\n function _hashPaymentChannelCommit(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n ));\n }\n\n // private functions (pure)\n\n function _computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n private\n pure\n returns (bytes32)\n {\n return keccak256(\n abi.encodePacked(\n sender,\n recipient,\n token,\n uid\n )\n );\n }\n}\n" + }, + "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ław Głogowski \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" + }, + "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" + }, + "src/common/libs/SafeMathLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n" + }, + "src/common/lifecycle/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski \n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n" + }, + "src/common/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ław Głogowski \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" + }, + "src/common/token/ERC20Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n" + }, + "src/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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "src/gateway/GatewayRecipient.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n" + }, + "src/payments/PaymentDepositAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/access/Controlled.sol\";\n\n\n/**\n * @title Payment deposit account\n *\n * @dev Simple account contract with only one method - `executeTransaction`\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentDepositAccount is Controlled {\n /**\n * @dev Public constructor\n */\n constructor() public payable Controlled() {}\n\n /**\n * @notice Allow receives\n */\n receive()\n external\n payable\n {\n //\n }\n\n // external functions\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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \n */\ncontract AccountBase {\n address public registry;\n}\n" + }, + "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" + }, + "src/common/libs/BytesLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski \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" + }, + "src/tokens/WrappedWeiToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski \n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n" + }, + "src/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 \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" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.12;\r\npragma experimental ABIEncoderV2;\r\n\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/**\r\n * @title Gateway\r\n *\r\n * @notice GSN replacement\r\n *\r\n * @author Stanisław Głogowski \r\n */\r\ncontract Gateway is Initializable, SignatureValidator {\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\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 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 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 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 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 // 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}" + }, + "src/ens/ENSController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./resolvers/ENSPubKeyResolver.sol\";\nimport \"./resolvers/ENSTextResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n\n/**\n * @title ENS controller\n *\n * @notice ENS subnode registrar\n *\n * @dev The process of adding root node consists of 3 steps:\n * 1. `submitNode` - should be called from ENS node owner,\n * 2. Change ENS node owner in ENS registry to ENS controller,\n * 3. `verifyNode` - should be called from previous ENS node owner,\n *\n * To register sub node, `msg.sender` need to send valid signature from one of guardian key.\n * Once registration is complete `msg.sender` becoming both node owner and `addr` record value.\n *\n * After registration sub node cannot be replaced.\n *\n * @author Stanisław Głogowski \n */\ncontract ENSController is Guarded, Initializable, SignatureValidator, GatewayRecipient, ENSAddressResolver, ENSNameResolver, ENSPubKeyResolver, ENSTextResolver {\n struct SubNodeRegistration {\n address account;\n bytes32 node;\n bytes32 label;\n }\n\n bytes4 private constant INTERFACE_META_ID = bytes4(keccak256(abi.encodePacked(\"supportsInterface(bytes4)\")));\n\n bytes32 private constant HASH_PREFIX_SUB_NODE_REGISTRATION = keccak256(\n \"SubNodeRegistration(address account,bytes32 node,bytes32 label)\"\n );\n\n ENSRegistry public registry;\n\n mapping(bytes32 => address) public nodeOwners;\n\n // events\n\n /**\n * @dev Emitted when new node is submitted\n * @param node node name hash\n * @param owner owner address\n */\n event NodeSubmitted(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when the existing owner is verified\n * @param node node name hash\n */\n event NodeVerified(\n bytes32 node\n );\n\n /**\n * @dev Emitted when new node is released\n * @param node node name hash\n * @param owner owner address\n */\n event NodeReleased(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when ENS registry address is changed\n * @param registry registry address\n */\n event RegistryChanged(\n address registry\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Guarded() Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSController` contract\n * @param registry_ ENS registry address\n * @param gateway_ gateway address\n */\n function initialize(\n ENSRegistry registry_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n registry = registry_;\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Sets registry\n * @param registry_ registry address\n */\n function setRegistry(\n ENSRegistry registry_\n )\n external\n onlyGuardian\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n require(\n registry_ != registry,\n \"ENSController: registry already set\"\n );\n\n registry = registry_;\n\n emit RegistryChanged(\n address(registry)\n );\n }\n\n /**\n * @notice Submits node\n * @dev Should be called from the current ENS node owner\n * @param node node name hash\n */\n function submitNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == address(0),\n \"ENSController: node already submitted\"\n );\n\n require(\n registry.owner(node) == owner,\n \"ENSController: invalid ens node owner\"\n );\n\n nodeOwners[node] = owner;\n\n emit NodeSubmitted(node, owner);\n }\n\n /**\n * @notice Verifies node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function verifyNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n require(\n registry.owner(node) == address(this),\n \"ENSController: invalid ens node owner\"\n );\n\n _setAddr(node, address(this));\n\n registry.setResolver(node, address(this));\n\n emit NodeVerified(node);\n }\n\n /**\n * @notice Releases node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function releaseNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(this),\n \"ENSController: node doesn't exist\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n registry.setOwner(node, owner);\n\n delete nodeOwners[node];\n\n emit NodeReleased(node, owner);\n }\n\n /**\n * @notice Sync address\n * @param node node name hash\n */\n function syncAddr(\n bytes32 node\n )\n external\n {\n address account = _getContextAccount();\n\n require(\n account == registry.owner(node),\n \"ENSController: caller is not the node owner\"\n );\n\n require(\n registry.resolver(node) == address(this),\n \"ENSController: invalid node resolver\"\n );\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already in sync\"\n );\n\n _setAddr(node, account);\n }\n\n /**\n * @notice Registers sub node\n * @param node node name hash\n * @param label label hash\n * @param guardianSignature guardian signature\n */\n function registerSubNode(\n bytes32 node,\n bytes32 label,\n bytes calldata guardianSignature\n )\n external\n {\n address account = _getContextAccount();\n\n bytes32 messageHash = _hashSubNodeRegistration(\n account,\n node,\n label\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"ENSController: invalid guardian signature\"\n );\n\n bytes32 subNode = keccak256(\n abi.encodePacked(\n node,\n label\n )\n );\n\n require(\n _addr(node) == address(this),\n \"ENSController: invalid node\"\n );\n\n require(\n _addr(subNode) == address(0),\n \"ENSController: label already taken\"\n );\n\n registry.setSubnodeRecord(node, label, address(this), address(this), 0);\n registry.setOwner(subNode, account);\n\n _setAddr(subNode, account);\n }\n\n // external functions (pure)\n function supportsInterface(\n bytes4 interfaceID\n )\n external\n pure\n returns(bool)\n {\n return interfaceID == INTERFACE_META_ID ||\n interfaceID == INTERFACE_ADDR_ID ||\n interfaceID == INTERFACE_ADDRESS_ID ||\n interfaceID == INTERFACE_NAME_ID ||\n interfaceID == INTERFACE_PUB_KEY_ID ||\n interfaceID == INTERFACE_TEXT_ID;\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `SubNodeRegistration` message payload\n * @param subNodeRegistration struct\n * @return hash\n */\n function hashSubNodeRegistration(\n SubNodeRegistration memory subNodeRegistration\n )\n public\n view\n returns (bytes32)\n {\n return _hashSubNodeRegistration(\n subNodeRegistration.account,\n subNodeRegistration.node,\n subNodeRegistration.label\n );\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n override\n view\n returns (bool)\n {\n return registry.owner(node) == _getContextAccount();\n }\n\n // private functions (views)\n\n function _hashSubNodeRegistration(\n address account,\n bytes32 node,\n bytes32 label\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_SUB_NODE_REGISTRATION, abi.encodePacked(\n account,\n node,\n label\n ));\n }\n}\n" + }, + "src/ens/resolvers/ENSAddressResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract address resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/AddrResolver.sol\n */\nabstract contract ENSAddressResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_ADDR_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32)\")));\n bytes4 internal constant INTERFACE_ADDRESS_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32,uint)\")));\n\n uint internal constant COIN_TYPE_ETH = 60;\n\n mapping(bytes32 => mapping(uint => bytes)) internal resolverAddresses;\n\n // events\n\n event AddrChanged(\n bytes32 indexed node,\n address addr\n );\n\n event AddressChanged(\n bytes32 indexed node,\n uint coinType,\n bytes newAddress\n );\n\n // external functions\n\n function setAddr(\n bytes32 node,\n address addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, addr_);\n }\n\n function setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, coinType, addr_);\n }\n\n // external functions (views)\n\n function addr(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return _addr(node);\n }\n\n function addr(\n bytes32 node,\n uint coinType\n )\n external\n view\n returns (bytes memory)\n {\n return resolverAddresses[node][coinType];\n }\n\n // internal functions\n\n function _setAddr(\n bytes32 node,\n address addr_\n )\n internal\n {\n _setAddr(node, COIN_TYPE_ETH, _addressToBytes(addr_));\n }\n\n function _setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n internal\n {\n emit AddressChanged(node, coinType, addr_);\n\n if(coinType == COIN_TYPE_ETH) {\n emit AddrChanged(node, _bytesToAddress(addr_));\n }\n\n resolverAddresses[node][coinType] = addr_;\n }\n\n // internal functions (views)\n\n function _addr(\n bytes32 node\n )\n internal\n view\n returns (address)\n {\n address result;\n\n bytes memory addr_ = resolverAddresses[node][COIN_TYPE_ETH];\n\n if (addr_.length > 0) {\n result = _bytesToAddress(addr_);\n }\n\n return result;\n }\n\n // private function (pure)\n\n function _bytesToAddress(\n bytes memory data\n )\n private\n pure\n returns(address payable)\n {\n address payable result;\n\n require(data.length == 20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 32)), exp(256, 12))\n }\n\n return result;\n }\n\n function _addressToBytes(\n address addr_\n )\n private\n pure\n returns(bytes memory)\n {\n bytes memory result = new bytes(20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(add(result, 32), mul(addr_, exp(256, 12)))\n }\n\n return result;\n }\n}\n" + }, + "src/ens/resolvers/ENSNameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract name resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/NameResolver.sol\n */\nabstract contract ENSNameResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_NAME_ID = bytes4(keccak256(abi.encodePacked(\"name(bytes32)\")));\n\n mapping(bytes32 => string) internal resolverNames;\n\n // events\n\n event NameChanged(\n bytes32 indexed node,\n string name\n );\n\n // external functions\n\n function setName(\n bytes32 node,\n string calldata name\n )\n external\n onlyNodeOwner(node)\n {\n resolverNames[node] = name;\n\n emit NameChanged(node, name);\n }\n\n // external functions (views)\n\n function name(\n bytes32 node\n )\n external\n view\n returns (string memory)\n {\n return resolverNames[node];\n }\n}\n" + }, + "src/ens/resolvers/ENSPubKeyResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract pub key resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/PubkeyResolver.sol\n */\nabstract contract ENSPubKeyResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_PUB_KEY_ID = bytes4(keccak256(abi.encodePacked(\"pubkey(bytes32)\")));\n\n struct PubKey {\n bytes32 x;\n bytes32 y;\n }\n\n mapping(bytes32 => PubKey) internal resolverPubKeys;\n\n // events\n\n event PubkeyChanged(\n bytes32 indexed node,\n bytes32 x,\n bytes32 y\n );\n\n // external functions (views)\n\n function setPubkey(\n bytes32 node,\n bytes32 x,\n bytes32 y\n )\n external\n onlyNodeOwner(node)\n {\n resolverPubKeys[node] = PubKey(x, y);\n\n emit PubkeyChanged(node, x, y);\n }\n\n // external functions (views)\n\n function pubkey(\n bytes32 node\n )\n external\n view\n returns (bytes32 x, bytes32 y)\n {\n return (resolverPubKeys[node].x, resolverPubKeys[node].y);\n }\n}\n" + }, + "src/ens/resolvers/ENSTextResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract text resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/TextResolver.sol\n */\nabstract contract ENSTextResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_TEXT_ID = bytes4(keccak256(abi.encodePacked(\"text(bytes32,string)\")));\n\n mapping(bytes32 => mapping(string => string)) internal resolverTexts;\n\n // events\n\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key\n );\n\n // external functions (views)\n\n function setText(\n bytes32 node,\n string calldata key,\n string calldata value\n )\n external\n onlyNodeOwner(node)\n {\n resolverTexts[node][key] = value;\n\n emit TextChanged(node, key, key);\n }\n\n // external functions (views)\n\n function text(\n bytes32 node,\n string calldata key\n )\n external\n view\n returns (string memory)\n {\n return resolverTexts[node][key];\n }\n}\n" + }, + "src/ens/ENSRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS registry\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\n */\ncontract ENSRegistry {\n struct Record {\n address owner;\n address resolver;\n uint64 ttl;\n }\n\n mapping (bytes32 => Record) private records;\n mapping (address => mapping(address => bool)) private operators;\n\n // events\n\n event NewOwner(\n bytes32 indexed node,\n bytes32 indexed label,\n address owner\n );\n\n event Transfer(\n bytes32 indexed node,\n address owner\n );\n\n event NewResolver(\n bytes32 indexed node,\n address resolver\n );\n\n event NewTTL(\n bytes32 indexed node,\n uint64 ttl\n );\n\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n // modifiers\n\n modifier authorised(\n bytes32 node\n )\n {\n address owner = records[node].owner;\n\n require(\n owner == msg.sender || operators[owner][msg.sender],\n \"ENSRegistry: reverted by authorised modifier\"\n );\n\n _;\n }\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n {\n // solhint-disable-next-line avoid-tx-origin\n records[0x0].owner = tx.origin;\n }\n\n // external functions\n\n function setRecord(\n bytes32 node,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n setOwner(node, owner_);\n\n _setResolverAndTTL(node, resolver_, ttl_);\n }\n\n function setTTL(\n bytes32 node,\n uint64 ttl_\n )\n external\n authorised(node)\n {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n bytes32 subNode = setSubnodeOwner(node, label, owner_);\n\n _setResolverAndTTL(subNode, resolver_, ttl_);\n }\n\n function setApprovalForAll(\n address operator,\n bool approved\n )\n external\n {\n operators[msg.sender][operator] = approved;\n\n emit ApprovalForAll(\n msg.sender,\n operator,\n approved\n );\n }\n\n // external functions (views)\n\n function owner(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n address addr = records[node].owner;\n\n if (addr == address(this)) {\n return address(0x0);\n }\n\n return addr;\n }\n\n function resolver(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return records[node].resolver;\n }\n\n function ttl(\n bytes32 node\n )\n external\n view\n returns (uint64)\n {\n return records[node].ttl;\n }\n\n function recordExists(\n bytes32 node\n )\n external\n view\n returns (bool)\n {\n return records[node].owner != address(0x0);\n }\n\n function isApprovedForAll(\n address owner_,\n address operator\n )\n external\n view\n returns (bool)\n {\n return operators[owner_][operator];\n }\n\n // public functions\n\n function setOwner(\n bytes32 node,\n address owner_\n )\n public\n authorised(node)\n {\n records[node].owner = owner_;\n\n emit Transfer(node, owner_);\n }\n\n function setResolver(\n bytes32 node,\n address resolver_\n )\n public\n authorised(node)\n {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner_\n )\n public\n authorised(node)\n returns(bytes32)\n {\n bytes32 subNode = keccak256(abi.encodePacked(node, label));\n\n records[subNode].owner = owner_;\n\n emit NewOwner(node, label, owner_);\n\n return subNode;\n }\n\n // private functions\n\n function _setResolverAndTTL(\n bytes32 node,\n address resolver_,\n uint64 ttl_\n )\n private\n {\n if (resolver_ != records[node].resolver) {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n if (ttl_ != records[node].ttl) {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n }\n}\n" + }, + "src/ens/resolvers/ENSAbstractResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS abstract resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/ResolverBase.sol\n */\nabstract contract ENSAbstractResolver {\n // modifiers\n\n modifier onlyNodeOwner(bytes32 node)\n {\n require(\n _isNodeOwner(node),\n \"ENSAbstractResolver: reverted by onlyNodeOwner modifier\"\n );\n\n _;\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n virtual\n view\n returns (bool);\n}\n" + }, + "src/ens/ENSReverseRegistrar.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/AddressLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS reverse registrar\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\n */\ncontract ENSReverseRegistrar is Initializable {\n using AddressLib for address;\n\n // namehash('addr.reverse')\n bytes32 public constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n ENSRegistry public registry;\n ENSNameResolver public resolver;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSReverseRegistrar` contract\n * @param registry_ ENS registry address\n * @param resolver_ ENS name resolver address\n */\n function initialize(\n ENSRegistry registry_,\n ENSNameResolver resolver_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n resolver = resolver_;\n }\n\n // external functions\n\n function claim(\n address owner\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, address(0));\n }\n\n function claimWithResolver(\n address owner,\n address resolver_\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, resolver_);\n }\n\n function setName(\n string memory name\n )\n public\n returns (bytes32)\n {\n bytes32 node = _claimWithResolver(address(this), address(resolver));\n\n resolver.setName(node, name);\n\n return node;\n }\n\n // external functions (pure)\n\n function node(\n address addr_\n )\n external\n pure\n returns (bytes32)\n {\n return keccak256(abi.encodePacked(ADDR_REVERSE_NODE, addr_.toSha3Hash()));\n }\n\n // private functions\n\n function _claimWithResolver(\n address owner,\n address resolver_\n )\n private\n returns (bytes32)\n {\n bytes32 label = address(msg.sender).toSha3Hash();\n bytes32 node_ = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n address currentOwner = registry.owner(node_);\n\n if (resolver_ != address(0x0) && resolver_ != registry.resolver(node_)) {\n if (currentOwner != address(this)) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this));\n currentOwner = address(this);\n }\n\n registry.setResolver(node_, resolver_);\n }\n\n // Update the owner if required\n if (currentOwner != owner) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);\n }\n\n return node_;\n }\n}\n" + }, + "src/common/libs/AddressLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Address library\n */\nlibrary AddressLib {\n /**\n * @notice Converts address into sha3 hash\n * @param self address\n * @return sha3 hash\n */\n function toSha3Hash(\n address self\n )\n internal\n pure\n returns (bytes32)\n {\n bytes32 result;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000\n\n for { let i := 40 } gt(i, 0) { } {\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n }\n\n result := keccak256(0, 40)\n }\n\n return result;\n }\n}\n" + }, + "src/ens/ENSHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS helper\n *\n * @author Stanisław Głogowski \n */\ncontract ENSHelper is Initializable {\n ENSRegistry public registry;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSLookupHelper` contract\n * @param registry_ ENS registry address\n */\n function initialize(\n ENSRegistry registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n /**\n * @notice Gets nodes addresses\n * @param nodes array of nodes\n * @return nodes addresses\n */\n function getAddresses(\n bytes32[] memory nodes\n )\n external\n view\n returns (address[] memory)\n {\n uint nodesLen = nodes.length;\n address[] memory result = new address[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getAddress(nodes[i]);\n }\n\n return result;\n }\n\n /**\n * @notice Gets nodes names\n * @param nodes array of nodes\n * @return nodes names\n */\n function getNames(\n bytes32[] memory nodes\n )\n external\n view\n returns (string[] memory)\n {\n uint nodesLen = nodes.length;\n string[] memory result = new string[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getName(nodes[i]);\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getAddress(\n bytes32 node\n )\n private\n view\n returns (address)\n {\n address result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSAddressResolver(resolver).addr(node) returns (address addr) {\n result = addr;\n } catch {\n //\n }\n }\n\n return result;\n }\n\n function _getName(\n bytes32 node\n )\n private\n view\n returns (string memory)\n {\n string memory result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSNameResolver(resolver).name(node) returns (string memory name) {\n result = name;\n } catch {\n //\n }\n }\n\n return result;\n }\n}\n" + }, + "src/common/account/AccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../lifecycle/Initializable.sol\";\nimport \"./AccountBase.sol\";\nimport \"./AccountRegistry.sol\";\n\n\n/**\n * @title Account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1 is Initializable, AccountBase {\n bytes32 constant private ERC777_TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(abi.encodePacked(\"ERC777TokensRecipient\"));\n bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n bytes4 constant private ERC1271_VALID_MESSAGE_HASH_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes32,bytes)\")));\n bytes4 constant private ERC1271_VALID_MESSAGE_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes,bytes)\")));\n bytes4 constant private ERC1271_INVALID_SIGNATURE = 0xffffffff;\n\n /**\n * @dev Internal constructor\n */\n constructor() internal Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `AccountImplementation` contract\n * @param registry_ registry address\n */\n function initialize(\n address registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n // ERC1820\n\n function canImplementInterfaceForAddress(\n bytes32 interfaceHash,\n address addr\n )\n external\n view\n returns(bytes32)\n {\n bytes32 result;\n\n if (interfaceHash == ERC777_TOKENS_RECIPIENT_INTERFACE_HASH && addr == address(this)) {\n result = ERC1820_ACCEPT_MAGIC;\n }\n\n return result;\n }\n\n // ERC1271\n\n function isValidSignature(\n bytes32 messageHash,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), messageHash, signature)\n ? ERC1271_VALID_MESSAGE_HASH_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n function isValidSignature(\n bytes calldata message,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), message, signature)\n ? ERC1271_VALID_MESSAGE_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n // external functions (pure)\n\n // ERC721\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC721Received.selector;\n }\n\n // ERC1155\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC1155Received.selector;\n }\n\n // ERC777\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n )\n external\n pure\n {}\n}\n" + }, + "src/personal/PersonalAccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/account/AccountImplementationV1.sol\";\n\n\n/**\n * @title Personal account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\n\n /**\n * @dev Public constructor\n */\n constructor() public AccountImplementationV1() {}\n}\n" + }, + "src/common/account/mocks/AccountImplementationV1Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountImplementationV1.sol\";\n\n\n/**\n * @title Account implementation mock (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1Mock is AccountImplementationV1 {\n /**\n * @dev Public constructor\n * @param registry_ account registry address\n */\n constructor(\n address registry_\n )\n public\n AccountImplementationV1()\n {\n registry = registry_;\n }\n}\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/bscTest/BalancesHelperV2.json b/deployments/bscTest/BalancesHelperV2.json new file mode 100644 index 00000000..9d05ac9b --- /dev/null +++ b/deployments/bscTest/BalancesHelperV2.json @@ -0,0 +1,144 @@ +{ + "address": "0xe5A160F89f330cc933816E896a3F36376DE0a835", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "AccountZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getBalances", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getSuperfluidWrappedTokenBalances", + "outputs": [ + { + "internalType": "int256[]", + "name": "", + "type": "int256[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "args": [], + "solcInputHash": "893c7c8579088197a1acbd2718e7b759", + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"AccountZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getSuperfluidWrappedTokenBalances\",\"outputs\":[{\"internalType\":\"int256[]\",\"name\":\"\",\"type\":\"int256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"AccountZeroAddress(address,address)\":[{\"notice\":\"Custom errors to handle address(0)\"}]},\"kind\":\"user\",\"methods\":{\"getBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple ERC20 tokens.\"},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple Wrapped Super Tokens.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/common/helpers/BalancesHelperV2.sol\":\"BalancesHelperV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0x6ebf1944ab804b8660eb6fc52f9fe84588cee01c2566a69023e59497e7d27f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperAgreement.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperfluidToken } from \\\"./ISuperfluidToken.sol\\\";\\n\\n/**\\n * @title Super agreement interface\\n * @author Superfluid\\n */\\ninterface ISuperAgreement {\\n\\n /**\\n * @dev Get the type of the agreement class\\n */\\n function agreementType() external view returns (bytes32);\\n\\n /**\\n * @dev Calculate the real-time balance for the account of this agreement class\\n * @param account Account the state belongs to\\n * @param time Time used for the calculation\\n * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement\\n * @return deposit Account deposit amount of this agreement\\n * @return owedDeposit Account owed deposit amount of this agreement\\n */\\n function realtimeBalanceOf(\\n ISuperfluidToken token,\\n address account,\\n uint256 time\\n )\\n external\\n view\\n returns (\\n int256 dynamicBalance,\\n uint256 deposit,\\n uint256 owedDeposit\\n );\\n\\n}\\n\",\"keccak256\":\"0xc3a6a907245116bcecc70fe4b207454012e8ce4fa190228fb8bbe39e0b1bc5cf\",\"license\":\"AGPLv3\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperAgreement } from \\\"./ISuperAgreement.sol\\\";\\n\\n\\n/**\\n * @title Superfluid token interface\\n * @author Superfluid\\n */\\ninterface ISuperfluidToken {\\n\\n /**************************************************************************\\n * Basic information\\n *************************************************************************/\\n\\n /**\\n * @dev Get superfluid host contract address\\n */\\n function getHost() external view returns(address host);\\n\\n /**\\n * @dev Encoded liquidation type data mainly used for handling stack to deep errors\\n *\\n * Note:\\n * - version: 1\\n * - liquidationType key:\\n * - 0 = reward account receives reward (PIC period)\\n * - 1 = liquidator account receives reward (Pleb period)\\n * - 2 = liquidator account receives reward (Pirate period/bailout)\\n */\\n struct LiquidationTypeData {\\n uint256 version;\\n uint8 liquidationType;\\n }\\n\\n /**************************************************************************\\n * Real-time balance functions\\n *************************************************************************/\\n\\n /**\\n * @dev Calculate the real balance of a user, taking in consideration all agreements of the account\\n * @param account for the query\\n * @param timestamp Time of balance\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOf(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit);\\n\\n /**\\n * @notice Calculate the realtime balance given the current host.getNow() value\\n * @dev realtimeBalanceOf with timestamp equals to block timestamp\\n * @param account for the query\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOfNow(\\n address account\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit,\\n uint256 timestamp);\\n\\n /**\\n * @notice Check if account is critical\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is critical (should use future)\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCritical(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is critical now (current host.getNow())\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCriticalNow(\\n address account\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is solvent\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is solvent (should use future)\\n * @return isSolvent\\n */\\n function isAccountSolvent(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Check if account is solvent now\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @return isSolvent\\n */\\n function isAccountSolventNow(\\n address account\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Get a list of agreements that is active for the account\\n * @dev An active agreement is one that has state for the account\\n * @param account Account to query\\n * @return activeAgreements List of accounts that have non-zero states for the account\\n */\\n function getAccountActiveAgreements(address account)\\n external view\\n returns(ISuperAgreement[] memory activeAgreements);\\n\\n\\n /**************************************************************************\\n * Super Agreement hosting functions\\n *************************************************************************/\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function createAgreement(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement created event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementCreated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Get data of the agreement\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @return data Data of the agreement\\n */\\n function getAgreementData(\\n address agreementClass,\\n bytes32 id,\\n uint dataLength\\n )\\n external view\\n returns(bytes32[] memory data);\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function updateAgreementData(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement updated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementUpdated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Close the agreement\\n * @param id Agreement ID\\n */\\n function terminateAgreement(\\n bytes32 id,\\n uint dataLength\\n )\\n external;\\n /**\\n * @dev Agreement terminated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n */\\n event AgreementTerminated(\\n address indexed agreementClass,\\n bytes32 id\\n );\\n\\n /**\\n * @dev Update agreement state slot\\n * @param account Account to be updated\\n *\\n * NOTE\\n * - To clear the storage out, provide zero-ed array of intended length\\n */\\n function updateAgreementStateSlot(\\n address account,\\n uint256 slotId,\\n bytes32[] calldata slotData\\n )\\n external;\\n /**\\n * @dev Agreement account state updated event\\n * @param agreementClass Contract address of the agreement\\n * @param account Account updated\\n * @param slotId slot id of the agreement state\\n */\\n event AgreementStateUpdated(\\n address indexed agreementClass,\\n address indexed account,\\n uint256 slotId\\n );\\n\\n /**\\n * @dev Get data of the slot of the state of an agreement\\n * @param agreementClass Contract address of the agreement\\n * @param account Account to query\\n * @param slotId slot id of the state\\n * @param dataLength length of the state data\\n */\\n function getAgreementStateSlot(\\n address agreementClass,\\n address account,\\n uint256 slotId,\\n uint dataLength\\n )\\n external view\\n returns (bytes32[] memory slotData);\\n\\n /**\\n * @notice Settle balance from an account by the agreement\\n * @dev The agreement needs to make sure that the balance delta is balanced afterwards\\n * @param account Account to query.\\n * @param delta Amount of balance delta to be settled\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function settleBalance(\\n address account,\\n int256 delta\\n )\\n external;\\n\\n /**\\n * @dev Make liquidation payouts (v2)\\n * @param id Agreement ID\\n * @param liquidationTypeData Data regarding the version of the liquidation schema and the type\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount\\n * @param targetAccount Account of the stream sender\\n * @param rewardAmount The amount the reward recepient account will receive\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n *\\n * - If a bailout is required (bailoutAmount > 0)\\n * - the actual reward (single deposit) goes to the executor,\\n * - while the reward account becomes the bailout account\\n * - total bailout include: bailout amount + reward amount\\n * - the targetAccount will be bailed out\\n * - If a bailout is not required\\n * - the targetAccount will pay the rewardAmount\\n * - the liquidator (reward account in PIC period) will receive the rewardAmount\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function makeLiquidationPayoutsV2\\n (\\n bytes32 id,\\n bytes memory liquidationTypeData,\\n address liquidatorAccount,\\n bool useDefaultRewardAccount,\\n address targetAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta\\n ) external;\\n /**\\n * @dev Agreement liquidation event v2 (including agent account)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param targetAccount Account of the stream sender\\n * @param rewardAccount Account that collects the reward or bails out insolvent accounts\\n * @param rewardAmount The amount the reward recipient account balance should change by\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n * @param liquidationTypeData The encoded liquidation type data including the version (how to decode)\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if the agreement is liquidated during the PIC period\\n * - the rewardAccount will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount\\n * - the targetAccount will pay for the rewardAmount\\n * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent\\n * - the liquidatorAccount will get the rewardAmount (remaining deposit)\\n * - the targetAccount will pay for the rewardAmount\\n * - if the targetAccount is insolvent\\n * - the liquidatorAccount will get the rewardAmount (single deposit)\\n * - the rewardAccount will pay for both the rewardAmount and bailoutAmount\\n * - the targetAccount will receive the bailoutAmount\\n */\\n event AgreementLiquidatedV2(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed liquidatorAccount,\\n address indexed targetAccount,\\n address rewardAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta,\\n bytes liquidationTypeData\\n );\\n\\n /**************************************************************************\\n * Function modifiers for access control and parameter validations\\n *\\n * While they cannot be explicitly stated in function definitions, they are\\n * listed in function definition comments instead for clarity.\\n *\\n * NOTE: solidity-coverage not supporting it\\n *************************************************************************/\\n\\n /// @dev The msg.sender must be host contract\\n //modifier onlyHost() virtual;\\n\\n /// @dev The msg.sender must be a listed agreement.\\n //modifier onlyAgreement() virtual;\\n\\n /**************************************************************************\\n * DEPRECATED\\n *************************************************************************/\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param rewardAccount Account that collect the reward\\n * @param rewardAmount Amount of liquidation reward\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event AgreementLiquidated(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed rewardAccount,\\n uint256 rewardAmount\\n );\\n\\n /**\\n * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy)\\n * @param bailoutAccount Account that bailout the penalty account\\n * @param bailoutAmount Amount of account bailout\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event Bailout(\\n address indexed bailoutAccount,\\n uint256 bailoutAmount\\n );\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2)\\n * @param liquidatorAccount Account of the agent that performed the liquidation.\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param bondAccount Account that collect the reward or bailout accounts\\n * @param rewardAmount Amount of liquidation reward\\n * @param bailoutAmount Amount of liquidation bailouot\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if bailout is equal to 0, then\\n * - the bondAccount will get the rewardAmount,\\n * - the penaltyAccount will pay for the rewardAmount.\\n * - if bailout is larger than 0, then\\n * - the liquidatorAccount will get the rewardAmouont,\\n * - the bondAccount will pay for both the rewardAmount and bailoutAmount,\\n * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.\\n */\\n event AgreementLiquidatedBy(\\n address liquidatorAccount,\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed bondAccount,\\n uint256 rewardAmount,\\n uint256 bailoutAmount\\n );\\n}\\n\",\"keccak256\":\"0x9189eaba9e856cc4932ea29eeaf4e89a09448dde13860591691ec122856fdc75\",\"license\":\"AGPLv3\"},\"src/common/helpers/BalancesHelperV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\n// solhint-disable-next-line\\r\\npragma solidity 0.8.4;\\r\\n\\r\\n/// @title BalancesHelperV2\\r\\n/// @author Luke Wickens \\r\\n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\\r\\n\\r\\nimport {ISuperfluidToken} from \\\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\\\";\\r\\nimport {IERC20} from \\\"@openzeppelin/contracts/interfaces/IERC20.sol\\\";\\r\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\r\\n\\r\\ncontract BalancesHelperV2 {\\r\\n using Address for address;\\r\\n\\r\\n /// @notice Custom errors to handle address(0)\\r\\n error AccountZeroAddress(address account, address token);\\r\\n error TokenZeroAddress(address account, address token);\\r\\n\\r\\n constructor() {}\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple ERC20 tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getBalances(address[] calldata accounts, address[] calldata tokens)\\r\\n external\\r\\n view\\r\\n returns (uint256[] memory)\\r\\n {\\r\\n uint256[] memory result = new uint256[](\\r\\n accounts.length * tokens.length\\r\\n );\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getBalance(accounts[i], tokens[j]);\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getSuperfluidWrappedTokenBalances(\\r\\n address[] calldata accounts,\\r\\n address[] calldata tokens\\r\\n ) external view returns (int256[] memory) {\\r\\n int256[] memory result = new int256[](accounts.length * tokens.length);\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getSuperfluidWrappedTokenBalance(\\r\\n accounts[i],\\r\\n tokens[j]\\r\\n );\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// Private fuctions\\r\\n\\r\\n /// @notice Returns balance of account for an ERC20 token.\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return balance of account as uint256.\\r\\n\\r\\n function _getBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (uint256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\\r\\n );\\r\\n\\r\\n return abi.decode(returnedData, (uint256));\\r\\n }\\r\\n\\r\\n /// @notice Returns real balance of a user, taking into consideration all agreements of account\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return available balance of account as int256.\\r\\n\\r\\n function _getSuperfluidWrappedTokenBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (int256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(\\r\\n ISuperfluidToken(token).realtimeBalanceOfNow.selector,\\r\\n account\\r\\n )\\r\\n );\\r\\n\\r\\n (int256 availableBalance, , , ) = abi.decode(\\r\\n returnedData,\\r\\n (int256, uint256, uint256, uint256)\\r\\n );\\r\\n return availableBalance;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xee88323570149a5d9e569da056eaa089cf4baacfb3713a0dd282090b1d0847d2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061108a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "devdoc": { + "kind": "dev", + "methods": { + "getBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "AccountZeroAddress(address,address)": [ + { + "notice": "Custom errors to handle address(0)" + } + ] + }, + "kind": "user", + "methods": { + "getBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple ERC20 tokens." + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple Wrapped Super Tokens." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/bscTest/GatewayV2.json b/deployments/bscTest/GatewayV2.json new file mode 100644 index 00000000..0ca6dc19 --- /dev/null +++ b/deployments/bscTest/GatewayV2.json @@ -0,0 +1,926 @@ +{ + "address": "0xBEd52610518788B931f7825301909e7616273d47", + "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": "0xd56fecb8c5a6ce335048541beffab457e5e7681958270321da8fe51c34e934bf", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "contractAddress": null, + "transactionIndex": 0, + "gasUsed": "2818644", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3f21f9bab1ab47a409014ede4167922d7ce8ec753b554859bcec97c6d8db1b13", + "transactionHash": "0xd56fecb8c5a6ce335048541beffab457e5e7681958270321da8fe51c34e934bf", + "logs": [], + "blockNumber": 23636060, + "cumulativeGasUsed": "2818644", + "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 \",\"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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 ", + "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" + } + } + } +} \ No newline at end of file diff --git a/deployments/bscTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json b/deployments/bscTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json new file mode 100644 index 00000000..fa380d29 --- /dev/null +++ b/deployments/bscTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json @@ -0,0 +1,142 @@ +{ + "language": "Solidity", + "sources": { + "src/payments/PaymentRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./PaymentDepositAccount.sol\";\n\n\n/**\n * @title Payment registry\n *\n * @notice A registry for payment and payment channels\n *\n * @dev the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message.\n * Process will be rejected when any of senders channels will be committed.\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct Deposit {\n address account;\n mapping(address => uint256) withdrawnAmount;\n mapping(address => uint256) exitLockedUntil;\n }\n\n struct PaymentChannel {\n uint256 committedAmount;\n }\n\n struct DepositWithdrawal {\n address owner;\n address token;\n uint256 amount;\n }\n\n struct PaymentChannelCommit {\n address sender;\n address recipient;\n address token;\n bytes32 uid;\n uint256 blockNumber;\n uint256 amount;\n }\n\n uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;\n\n bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(\n \"DepositWithdrawal(address owner,address token,uint256 amount)\"\n );\n bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(\n \"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n uint256 public depositExitLockPeriod;\n\n mapping(address => Deposit) private deposits;\n mapping(bytes32 => PaymentChannel) private paymentChannels;\n\n // events\n\n /**\n * @dev Emitted when the deposit account is deployed\n * @param depositAccount deposit account address\n * @param owner owner address\n */\n event DepositAccountDeployed(\n address depositAccount,\n address owner\n );\n\n /**\n * @dev Emitted when the deposit exist is requested\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param lockedUntil deposit exist locked util time\n */\n event DepositExitRequested(\n address depositAccount,\n address owner,\n address token,\n uint256 lockedUntil\n );\n\n /**\n * @dev Emitted when the deposit exist is completed\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount deposit exist amount\n */\n event DepositExitCompleted(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the deposit exist is rejected\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n */\n event DepositExitRejected(\n address depositAccount,\n address owner,\n address token\n );\n\n /**\n * @dev Emitted when the deposit has been withdrawn\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount withdrawn amount\n */\n event DepositWithdrawn(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment channel has been committed\n * @param hash channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @param amount committed amount\n */\n event PaymentChannelCommitted(\n bytes32 hash,\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentWithdrawn(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been deposited\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentDeposited(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn and deposited (split)\n * @param channelHash channel hash\n * @param totalValue payment total value\n * @param depositValue payment deposited value\n */\n event PaymentSplit(\n bytes32 channelHash,\n uint256 totalValue,\n uint256 depositValue\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initialize `PaymentRegistry` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n * @param depositExitLockPeriod_ deposit exit lock period\n * @param guardians_ array of guardians addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_,\n uint256 depositExitLockPeriod_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n if (depositExitLockPeriod_ == 0) {\n depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;\n } else {\n depositExitLockPeriod = depositExitLockPeriod_;\n }\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Deploys deposit account\n * @param owner owner address\n */\n function deployDepositAccount(\n address owner\n )\n external\n {\n _deployDepositAccount(owner);\n }\n\n /**\n * @notice Requests deposit exit\n * @param token token address\n */\n function requestDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil == 0,\n \"PaymentRegistry: deposit exit already requested\"\n );\n\n _deployDepositAccount(owner);\n\n // solhint-disable-next-line not-rely-on-time\n lockedUntil = now.add(depositExitLockPeriod);\n\n deposits[owner].exitLockedUntil[token] = lockedUntil;\n\n emit DepositExitRequested(\n deposits[owner].account,\n owner,\n token,\n lockedUntil\n );\n }\n\n /**\n * @notice Processes deposit exit\n * @param token token address\n */\n function processDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil != 0,\n \"PaymentRegistry: deposit exit not requested\"\n );\n\n require(\n // solhint-disable-next-line not-rely-on-time\n lockedUntil <= now,\n \"PaymentRegistry: deposit exit locked\"\n );\n\n deposits[owner].exitLockedUntil[token] = 0;\n\n address depositAccount = deposits[owner].account;\n uint256 depositValue;\n\n if (token == address(0)) {\n depositValue = depositAccount.balance;\n } else {\n depositValue = ERC20Token(token).balanceOf(depositAccount);\n }\n\n _transferFromDeposit(\n depositAccount,\n owner,\n token,\n depositValue\n );\n\n emit DepositExitCompleted(\n depositAccount,\n owner,\n token,\n depositValue\n );\n }\n\n /**\n * @notice Withdraws deposit\n * @param token token address\n * @param amount amount to withdraw\n * @param guardianSignature guardian signature\n */\n function withdrawDeposit(\n address token,\n uint256 amount,\n bytes calldata guardianSignature\n )\n external\n {\n address owner = _getContextAccount();\n uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);\n\n require(\n value > 0,\n \"PaymentRegistry: invalid amount\"\n );\n\n bytes32 messageHash = _hashDepositWithdrawal(\n owner,\n token,\n amount\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n deposits[owner].withdrawnAmount[token] = amount;\n\n _verifyDepositExitOrDeployAccount(owner, token);\n\n _transferFromDeposit(\n deposits[owner].account,\n owner,\n token,\n value\n );\n\n emit DepositWithdrawn(\n deposits[owner].account,\n owner,\n token,\n amount\n );\n }\n\n /**\n * @notice Commits payment channel and withdraw payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndWithdraw(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue\n );\n\n emit PaymentWithdrawn(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel and deposit payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndDeposit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(recipient),\n token,\n paymentValue\n );\n\n emit PaymentDeposited(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel, withdraws and deposits (split) payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param depositPaymentValue amount to deposit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndSplit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n uint256 depositPaymentValue,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferSplitFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue,\n depositPaymentValue\n );\n\n emit PaymentSplit(hash, paymentValue, depositPaymentValue);\n }\n\n // external functions (views)\n\n /**\n * @notice Computes deposit account address\n * @param owner owner address\n * @return deposit account address\n */\n function computeDepositAccountAddress(\n address owner\n )\n external\n view\n returns (address)\n {\n return _computeDepositAccountAddress(owner);\n }\n\n /**\n * @notice Checks if deposit account is deployed\n * @param owner owner address\n * @return true when deposit account is deployed\n */\n function isDepositAccountDeployed(\n address owner\n )\n external\n view\n returns (bool)\n {\n return deposits[owner].account != address(0);\n }\n\n /**\n * @notice Gets deposit exit locked until time\n * @param owner owner address\n * @param token token address\n * @return locked until time\n */\n function getDepositExitLockedUntil(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].exitLockedUntil[token];\n }\n\n /**\n * @notice Gets deposit withdrawn amount\n * @param owner owner address\n * @param token token address\n * @return withdrawn amount\n */\n function getDepositWithdrawnAmount(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].withdrawnAmount[token];\n }\n\n /**\n * @notice Gets payment channel committed amount\n * @param hash payment channel hash\n * @return committed amount\n */\n function getPaymentChannelCommittedAmount(\n bytes32 hash\n )\n external\n view\n returns (uint256)\n {\n return paymentChannels[hash].committedAmount;\n }\n\n // external functions (pure)\n\n /**\n * @notice Computes payment channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @return hash\n */\n function computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n external\n pure\n returns (bytes32)\n {\n return _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DepositWithdrawal` message payload\n * @param depositWithdrawal struct\n * @return hash\n */\n function hashDepositWithdrawal(\n DepositWithdrawal memory depositWithdrawal\n )\n public\n view\n returns (bytes32)\n {\n return _hashDepositWithdrawal(\n depositWithdrawal.owner,\n depositWithdrawal.token,\n depositWithdrawal.amount\n );\n }\n\n /**\n * @notice Hashes `PaymentChannelCommit` message payload\n * @param paymentChannelCommit struct\n * @return hash\n */\n function hashPaymentChannelCommit(\n PaymentChannelCommit memory paymentChannelCommit\n )\n public\n view\n returns (bytes32)\n {\n return _hashPaymentChannelCommit(\n paymentChannelCommit.sender,\n paymentChannelCommit.recipient,\n paymentChannelCommit.token,\n paymentChannelCommit.uid,\n paymentChannelCommit.blockNumber,\n paymentChannelCommit.amount\n );\n }\n\n // private functions\n\n function _deployDepositAccount(\n address owner\n )\n private\n {\n if (deposits[owner].account == address(0)) {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());\n\n emit DepositAccountDeployed(\n deposits[owner].account,\n owner\n );\n }\n }\n\n function _verifyDepositExitOrDeployAccount(\n address owner,\n address token\n )\n private\n {\n if (deposits[owner].exitLockedUntil[token] > 0) {\n deposits[owner].exitLockedUntil[token] = 0;\n\n emit DepositExitRejected(\n deposits[owner].account,\n owner,\n token\n );\n } else {\n _deployDepositAccount(owner);\n }\n }\n\n function _commitPaymentChannel(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes memory senderSignature,\n bytes memory guardianSignature\n )\n private\n returns (bytes32 hash, address depositAccount, uint256 paymentValue)\n {\n bytes32 messageHash = _hashPaymentChannelCommit(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n );\n\n if (senderSignature.length == 0) {\n require(\n externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),\n \"PaymentRegistry: invalid guardian signature\"\n );\n } else {\n address signer = messageHash.recoverAddress(senderSignature);\n\n if (sender != signer) {\n require(\n personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||\n externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),\n \"PaymentRegistry: invalid sender signature\"\n );\n }\n }\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n hash = _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n\n /// @dev calc payment value\n paymentValue = amount.sub(paymentChannels[hash].committedAmount);\n\n require(\n paymentValue != 0,\n \"PaymentRegistry: invalid payment value\"\n );\n\n paymentChannels[hash].committedAmount = amount;\n\n _verifyDepositExitOrDeployAccount(sender, token);\n\n depositAccount = deposits[sender].account;\n\n emit PaymentChannelCommitted(\n hash,\n sender,\n recipient,\n token,\n uid,\n amount\n );\n\n return (hash, depositAccount, paymentValue);\n }\n\n function _transferFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 value\n )\n private\n {\n if (token == address(0)) {\n PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n to,\n value,\n new bytes(0)\n );\n } else {\n bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n token,\n 0,\n abi.encodeWithSelector(\n ERC20Token(token).transfer.selector,\n to,\n value\n )\n );\n\n if (response.length > 0) {\n require(\n abi.decode(response, (bool)),\n \"PaymentRegistry: ERC20Token transfer reverted\"\n );\n }\n }\n }\n\n function _transferSplitFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 paymentValue,\n uint256 depositValue\n )\n private\n {\n require(\n depositValue > 0,\n \"PaymentRegistry: invalid deposit value\"\n );\n\n uint256 withdrawValue = paymentValue.sub(depositValue);\n\n require(\n withdrawValue > 0,\n \"PaymentRegistry: invalid withdraw value\"\n );\n\n _transferFromDeposit(\n depositAccount,\n to,\n token,\n withdrawValue\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(to),\n token,\n depositValue\n );\n }\n\n // private functions (views)\n\n function _computeDepositAccountAddress(\n address owner\n )\n private\n view\n returns (address)\n {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n bytes memory creationCode = type(PaymentDepositAccount).creationCode;\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 function _hashDepositWithdrawal(\n address owner,\n address token,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(\n owner,\n token,\n amount\n ));\n }\n\n function _hashPaymentChannelCommit(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n ));\n }\n\n // private functions (pure)\n\n function _computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n private\n pure\n returns (bytes32)\n {\n return keccak256(\n abi.encodePacked(\n sender,\n recipient,\n token,\n uid\n )\n );\n }\n}\n" + }, + "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ław Głogowski \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" + }, + "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" + }, + "src/common/libs/SafeMathLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n" + }, + "src/common/lifecycle/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski \n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n" + }, + "src/common/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ław Głogowski \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" + }, + "src/common/token/ERC20Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n" + }, + "src/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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "src/gateway/GatewayRecipient.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n" + }, + "src/payments/PaymentDepositAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/access/Controlled.sol\";\n\n\n/**\n * @title Payment deposit account\n *\n * @dev Simple account contract with only one method - `executeTransaction`\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentDepositAccount is Controlled {\n /**\n * @dev Public constructor\n */\n constructor() public payable Controlled() {}\n\n /**\n * @notice Allow receives\n */\n receive()\n external\n payable\n {\n //\n }\n\n // external functions\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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \n */\ncontract AccountBase {\n address public registry;\n}\n" + }, + "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" + }, + "src/common/libs/BytesLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski \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" + }, + "src/tokens/WrappedWeiToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski \n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n" + }, + "src/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 \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" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.12;\r\npragma experimental ABIEncoderV2;\r\n\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/**\r\n * @title Gateway\r\n *\r\n * @notice GSN replacement\r\n *\r\n * @author Stanisław Głogowski \r\n */\r\ncontract Gateway is Initializable, SignatureValidator {\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\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 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 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 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 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 // 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}" + }, + "src/ens/ENSController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./resolvers/ENSPubKeyResolver.sol\";\nimport \"./resolvers/ENSTextResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n\n/**\n * @title ENS controller\n *\n * @notice ENS subnode registrar\n *\n * @dev The process of adding root node consists of 3 steps:\n * 1. `submitNode` - should be called from ENS node owner,\n * 2. Change ENS node owner in ENS registry to ENS controller,\n * 3. `verifyNode` - should be called from previous ENS node owner,\n *\n * To register sub node, `msg.sender` need to send valid signature from one of guardian key.\n * Once registration is complete `msg.sender` becoming both node owner and `addr` record value.\n *\n * After registration sub node cannot be replaced.\n *\n * @author Stanisław Głogowski \n */\ncontract ENSController is Guarded, Initializable, SignatureValidator, GatewayRecipient, ENSAddressResolver, ENSNameResolver, ENSPubKeyResolver, ENSTextResolver {\n struct SubNodeRegistration {\n address account;\n bytes32 node;\n bytes32 label;\n }\n\n bytes4 private constant INTERFACE_META_ID = bytes4(keccak256(abi.encodePacked(\"supportsInterface(bytes4)\")));\n\n bytes32 private constant HASH_PREFIX_SUB_NODE_REGISTRATION = keccak256(\n \"SubNodeRegistration(address account,bytes32 node,bytes32 label)\"\n );\n\n ENSRegistry public registry;\n\n mapping(bytes32 => address) public nodeOwners;\n\n // events\n\n /**\n * @dev Emitted when new node is submitted\n * @param node node name hash\n * @param owner owner address\n */\n event NodeSubmitted(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when the existing owner is verified\n * @param node node name hash\n */\n event NodeVerified(\n bytes32 node\n );\n\n /**\n * @dev Emitted when new node is released\n * @param node node name hash\n * @param owner owner address\n */\n event NodeReleased(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when ENS registry address is changed\n * @param registry registry address\n */\n event RegistryChanged(\n address registry\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Guarded() Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSController` contract\n * @param registry_ ENS registry address\n * @param gateway_ gateway address\n */\n function initialize(\n ENSRegistry registry_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n registry = registry_;\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Sets registry\n * @param registry_ registry address\n */\n function setRegistry(\n ENSRegistry registry_\n )\n external\n onlyGuardian\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n require(\n registry_ != registry,\n \"ENSController: registry already set\"\n );\n\n registry = registry_;\n\n emit RegistryChanged(\n address(registry)\n );\n }\n\n /**\n * @notice Submits node\n * @dev Should be called from the current ENS node owner\n * @param node node name hash\n */\n function submitNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == address(0),\n \"ENSController: node already submitted\"\n );\n\n require(\n registry.owner(node) == owner,\n \"ENSController: invalid ens node owner\"\n );\n\n nodeOwners[node] = owner;\n\n emit NodeSubmitted(node, owner);\n }\n\n /**\n * @notice Verifies node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function verifyNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n require(\n registry.owner(node) == address(this),\n \"ENSController: invalid ens node owner\"\n );\n\n _setAddr(node, address(this));\n\n registry.setResolver(node, address(this));\n\n emit NodeVerified(node);\n }\n\n /**\n * @notice Releases node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function releaseNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(this),\n \"ENSController: node doesn't exist\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n registry.setOwner(node, owner);\n\n delete nodeOwners[node];\n\n emit NodeReleased(node, owner);\n }\n\n /**\n * @notice Sync address\n * @param node node name hash\n */\n function syncAddr(\n bytes32 node\n )\n external\n {\n address account = _getContextAccount();\n\n require(\n account == registry.owner(node),\n \"ENSController: caller is not the node owner\"\n );\n\n require(\n registry.resolver(node) == address(this),\n \"ENSController: invalid node resolver\"\n );\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already in sync\"\n );\n\n _setAddr(node, account);\n }\n\n /**\n * @notice Registers sub node\n * @param node node name hash\n * @param label label hash\n * @param guardianSignature guardian signature\n */\n function registerSubNode(\n bytes32 node,\n bytes32 label,\n bytes calldata guardianSignature\n )\n external\n {\n address account = _getContextAccount();\n\n bytes32 messageHash = _hashSubNodeRegistration(\n account,\n node,\n label\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"ENSController: invalid guardian signature\"\n );\n\n bytes32 subNode = keccak256(\n abi.encodePacked(\n node,\n label\n )\n );\n\n require(\n _addr(node) == address(this),\n \"ENSController: invalid node\"\n );\n\n require(\n _addr(subNode) == address(0),\n \"ENSController: label already taken\"\n );\n\n registry.setSubnodeRecord(node, label, address(this), address(this), 0);\n registry.setOwner(subNode, account);\n\n _setAddr(subNode, account);\n }\n\n // external functions (pure)\n function supportsInterface(\n bytes4 interfaceID\n )\n external\n pure\n returns(bool)\n {\n return interfaceID == INTERFACE_META_ID ||\n interfaceID == INTERFACE_ADDR_ID ||\n interfaceID == INTERFACE_ADDRESS_ID ||\n interfaceID == INTERFACE_NAME_ID ||\n interfaceID == INTERFACE_PUB_KEY_ID ||\n interfaceID == INTERFACE_TEXT_ID;\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `SubNodeRegistration` message payload\n * @param subNodeRegistration struct\n * @return hash\n */\n function hashSubNodeRegistration(\n SubNodeRegistration memory subNodeRegistration\n )\n public\n view\n returns (bytes32)\n {\n return _hashSubNodeRegistration(\n subNodeRegistration.account,\n subNodeRegistration.node,\n subNodeRegistration.label\n );\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n override\n view\n returns (bool)\n {\n return registry.owner(node) == _getContextAccount();\n }\n\n // private functions (views)\n\n function _hashSubNodeRegistration(\n address account,\n bytes32 node,\n bytes32 label\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_SUB_NODE_REGISTRATION, abi.encodePacked(\n account,\n node,\n label\n ));\n }\n}\n" + }, + "src/ens/resolvers/ENSAddressResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract address resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/AddrResolver.sol\n */\nabstract contract ENSAddressResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_ADDR_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32)\")));\n bytes4 internal constant INTERFACE_ADDRESS_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32,uint)\")));\n\n uint internal constant COIN_TYPE_ETH = 60;\n\n mapping(bytes32 => mapping(uint => bytes)) internal resolverAddresses;\n\n // events\n\n event AddrChanged(\n bytes32 indexed node,\n address addr\n );\n\n event AddressChanged(\n bytes32 indexed node,\n uint coinType,\n bytes newAddress\n );\n\n // external functions\n\n function setAddr(\n bytes32 node,\n address addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, addr_);\n }\n\n function setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, coinType, addr_);\n }\n\n // external functions (views)\n\n function addr(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return _addr(node);\n }\n\n function addr(\n bytes32 node,\n uint coinType\n )\n external\n view\n returns (bytes memory)\n {\n return resolverAddresses[node][coinType];\n }\n\n // internal functions\n\n function _setAddr(\n bytes32 node,\n address addr_\n )\n internal\n {\n _setAddr(node, COIN_TYPE_ETH, _addressToBytes(addr_));\n }\n\n function _setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n internal\n {\n emit AddressChanged(node, coinType, addr_);\n\n if(coinType == COIN_TYPE_ETH) {\n emit AddrChanged(node, _bytesToAddress(addr_));\n }\n\n resolverAddresses[node][coinType] = addr_;\n }\n\n // internal functions (views)\n\n function _addr(\n bytes32 node\n )\n internal\n view\n returns (address)\n {\n address result;\n\n bytes memory addr_ = resolverAddresses[node][COIN_TYPE_ETH];\n\n if (addr_.length > 0) {\n result = _bytesToAddress(addr_);\n }\n\n return result;\n }\n\n // private function (pure)\n\n function _bytesToAddress(\n bytes memory data\n )\n private\n pure\n returns(address payable)\n {\n address payable result;\n\n require(data.length == 20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 32)), exp(256, 12))\n }\n\n return result;\n }\n\n function _addressToBytes(\n address addr_\n )\n private\n pure\n returns(bytes memory)\n {\n bytes memory result = new bytes(20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(add(result, 32), mul(addr_, exp(256, 12)))\n }\n\n return result;\n }\n}\n" + }, + "src/ens/resolvers/ENSNameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract name resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/NameResolver.sol\n */\nabstract contract ENSNameResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_NAME_ID = bytes4(keccak256(abi.encodePacked(\"name(bytes32)\")));\n\n mapping(bytes32 => string) internal resolverNames;\n\n // events\n\n event NameChanged(\n bytes32 indexed node,\n string name\n );\n\n // external functions\n\n function setName(\n bytes32 node,\n string calldata name\n )\n external\n onlyNodeOwner(node)\n {\n resolverNames[node] = name;\n\n emit NameChanged(node, name);\n }\n\n // external functions (views)\n\n function name(\n bytes32 node\n )\n external\n view\n returns (string memory)\n {\n return resolverNames[node];\n }\n}\n" + }, + "src/ens/resolvers/ENSPubKeyResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract pub key resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/PubkeyResolver.sol\n */\nabstract contract ENSPubKeyResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_PUB_KEY_ID = bytes4(keccak256(abi.encodePacked(\"pubkey(bytes32)\")));\n\n struct PubKey {\n bytes32 x;\n bytes32 y;\n }\n\n mapping(bytes32 => PubKey) internal resolverPubKeys;\n\n // events\n\n event PubkeyChanged(\n bytes32 indexed node,\n bytes32 x,\n bytes32 y\n );\n\n // external functions (views)\n\n function setPubkey(\n bytes32 node,\n bytes32 x,\n bytes32 y\n )\n external\n onlyNodeOwner(node)\n {\n resolverPubKeys[node] = PubKey(x, y);\n\n emit PubkeyChanged(node, x, y);\n }\n\n // external functions (views)\n\n function pubkey(\n bytes32 node\n )\n external\n view\n returns (bytes32 x, bytes32 y)\n {\n return (resolverPubKeys[node].x, resolverPubKeys[node].y);\n }\n}\n" + }, + "src/ens/resolvers/ENSTextResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract text resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/TextResolver.sol\n */\nabstract contract ENSTextResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_TEXT_ID = bytes4(keccak256(abi.encodePacked(\"text(bytes32,string)\")));\n\n mapping(bytes32 => mapping(string => string)) internal resolverTexts;\n\n // events\n\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key\n );\n\n // external functions (views)\n\n function setText(\n bytes32 node,\n string calldata key,\n string calldata value\n )\n external\n onlyNodeOwner(node)\n {\n resolverTexts[node][key] = value;\n\n emit TextChanged(node, key, key);\n }\n\n // external functions (views)\n\n function text(\n bytes32 node,\n string calldata key\n )\n external\n view\n returns (string memory)\n {\n return resolverTexts[node][key];\n }\n}\n" + }, + "src/ens/ENSRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS registry\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\n */\ncontract ENSRegistry {\n struct Record {\n address owner;\n address resolver;\n uint64 ttl;\n }\n\n mapping (bytes32 => Record) private records;\n mapping (address => mapping(address => bool)) private operators;\n\n // events\n\n event NewOwner(\n bytes32 indexed node,\n bytes32 indexed label,\n address owner\n );\n\n event Transfer(\n bytes32 indexed node,\n address owner\n );\n\n event NewResolver(\n bytes32 indexed node,\n address resolver\n );\n\n event NewTTL(\n bytes32 indexed node,\n uint64 ttl\n );\n\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n // modifiers\n\n modifier authorised(\n bytes32 node\n )\n {\n address owner = records[node].owner;\n\n require(\n owner == msg.sender || operators[owner][msg.sender],\n \"ENSRegistry: reverted by authorised modifier\"\n );\n\n _;\n }\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n {\n // solhint-disable-next-line avoid-tx-origin\n records[0x0].owner = tx.origin;\n }\n\n // external functions\n\n function setRecord(\n bytes32 node,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n setOwner(node, owner_);\n\n _setResolverAndTTL(node, resolver_, ttl_);\n }\n\n function setTTL(\n bytes32 node,\n uint64 ttl_\n )\n external\n authorised(node)\n {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n bytes32 subNode = setSubnodeOwner(node, label, owner_);\n\n _setResolverAndTTL(subNode, resolver_, ttl_);\n }\n\n function setApprovalForAll(\n address operator,\n bool approved\n )\n external\n {\n operators[msg.sender][operator] = approved;\n\n emit ApprovalForAll(\n msg.sender,\n operator,\n approved\n );\n }\n\n // external functions (views)\n\n function owner(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n address addr = records[node].owner;\n\n if (addr == address(this)) {\n return address(0x0);\n }\n\n return addr;\n }\n\n function resolver(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return records[node].resolver;\n }\n\n function ttl(\n bytes32 node\n )\n external\n view\n returns (uint64)\n {\n return records[node].ttl;\n }\n\n function recordExists(\n bytes32 node\n )\n external\n view\n returns (bool)\n {\n return records[node].owner != address(0x0);\n }\n\n function isApprovedForAll(\n address owner_,\n address operator\n )\n external\n view\n returns (bool)\n {\n return operators[owner_][operator];\n }\n\n // public functions\n\n function setOwner(\n bytes32 node,\n address owner_\n )\n public\n authorised(node)\n {\n records[node].owner = owner_;\n\n emit Transfer(node, owner_);\n }\n\n function setResolver(\n bytes32 node,\n address resolver_\n )\n public\n authorised(node)\n {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner_\n )\n public\n authorised(node)\n returns(bytes32)\n {\n bytes32 subNode = keccak256(abi.encodePacked(node, label));\n\n records[subNode].owner = owner_;\n\n emit NewOwner(node, label, owner_);\n\n return subNode;\n }\n\n // private functions\n\n function _setResolverAndTTL(\n bytes32 node,\n address resolver_,\n uint64 ttl_\n )\n private\n {\n if (resolver_ != records[node].resolver) {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n if (ttl_ != records[node].ttl) {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n }\n}\n" + }, + "src/ens/resolvers/ENSAbstractResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS abstract resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/ResolverBase.sol\n */\nabstract contract ENSAbstractResolver {\n // modifiers\n\n modifier onlyNodeOwner(bytes32 node)\n {\n require(\n _isNodeOwner(node),\n \"ENSAbstractResolver: reverted by onlyNodeOwner modifier\"\n );\n\n _;\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n virtual\n view\n returns (bool);\n}\n" + }, + "src/ens/ENSReverseRegistrar.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/AddressLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS reverse registrar\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\n */\ncontract ENSReverseRegistrar is Initializable {\n using AddressLib for address;\n\n // namehash('addr.reverse')\n bytes32 public constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n ENSRegistry public registry;\n ENSNameResolver public resolver;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSReverseRegistrar` contract\n * @param registry_ ENS registry address\n * @param resolver_ ENS name resolver address\n */\n function initialize(\n ENSRegistry registry_,\n ENSNameResolver resolver_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n resolver = resolver_;\n }\n\n // external functions\n\n function claim(\n address owner\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, address(0));\n }\n\n function claimWithResolver(\n address owner,\n address resolver_\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, resolver_);\n }\n\n function setName(\n string memory name\n )\n public\n returns (bytes32)\n {\n bytes32 node = _claimWithResolver(address(this), address(resolver));\n\n resolver.setName(node, name);\n\n return node;\n }\n\n // external functions (pure)\n\n function node(\n address addr_\n )\n external\n pure\n returns (bytes32)\n {\n return keccak256(abi.encodePacked(ADDR_REVERSE_NODE, addr_.toSha3Hash()));\n }\n\n // private functions\n\n function _claimWithResolver(\n address owner,\n address resolver_\n )\n private\n returns (bytes32)\n {\n bytes32 label = address(msg.sender).toSha3Hash();\n bytes32 node_ = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n address currentOwner = registry.owner(node_);\n\n if (resolver_ != address(0x0) && resolver_ != registry.resolver(node_)) {\n if (currentOwner != address(this)) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this));\n currentOwner = address(this);\n }\n\n registry.setResolver(node_, resolver_);\n }\n\n // Update the owner if required\n if (currentOwner != owner) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);\n }\n\n return node_;\n }\n}\n" + }, + "src/common/libs/AddressLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Address library\n */\nlibrary AddressLib {\n /**\n * @notice Converts address into sha3 hash\n * @param self address\n * @return sha3 hash\n */\n function toSha3Hash(\n address self\n )\n internal\n pure\n returns (bytes32)\n {\n bytes32 result;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000\n\n for { let i := 40 } gt(i, 0) { } {\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n }\n\n result := keccak256(0, 40)\n }\n\n return result;\n }\n}\n" + }, + "src/ens/ENSHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS helper\n *\n * @author Stanisław Głogowski \n */\ncontract ENSHelper is Initializable {\n ENSRegistry public registry;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSLookupHelper` contract\n * @param registry_ ENS registry address\n */\n function initialize(\n ENSRegistry registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n /**\n * @notice Gets nodes addresses\n * @param nodes array of nodes\n * @return nodes addresses\n */\n function getAddresses(\n bytes32[] memory nodes\n )\n external\n view\n returns (address[] memory)\n {\n uint nodesLen = nodes.length;\n address[] memory result = new address[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getAddress(nodes[i]);\n }\n\n return result;\n }\n\n /**\n * @notice Gets nodes names\n * @param nodes array of nodes\n * @return nodes names\n */\n function getNames(\n bytes32[] memory nodes\n )\n external\n view\n returns (string[] memory)\n {\n uint nodesLen = nodes.length;\n string[] memory result = new string[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getName(nodes[i]);\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getAddress(\n bytes32 node\n )\n private\n view\n returns (address)\n {\n address result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSAddressResolver(resolver).addr(node) returns (address addr) {\n result = addr;\n } catch {\n //\n }\n }\n\n return result;\n }\n\n function _getName(\n bytes32 node\n )\n private\n view\n returns (string memory)\n {\n string memory result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSNameResolver(resolver).name(node) returns (string memory name) {\n result = name;\n } catch {\n //\n }\n }\n\n return result;\n }\n}\n" + }, + "src/common/account/AccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../lifecycle/Initializable.sol\";\nimport \"./AccountBase.sol\";\nimport \"./AccountRegistry.sol\";\n\n\n/**\n * @title Account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1 is Initializable, AccountBase {\n bytes32 constant private ERC777_TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(abi.encodePacked(\"ERC777TokensRecipient\"));\n bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n bytes4 constant private ERC1271_VALID_MESSAGE_HASH_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes32,bytes)\")));\n bytes4 constant private ERC1271_VALID_MESSAGE_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes,bytes)\")));\n bytes4 constant private ERC1271_INVALID_SIGNATURE = 0xffffffff;\n\n /**\n * @dev Internal constructor\n */\n constructor() internal Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `AccountImplementation` contract\n * @param registry_ registry address\n */\n function initialize(\n address registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n // ERC1820\n\n function canImplementInterfaceForAddress(\n bytes32 interfaceHash,\n address addr\n )\n external\n view\n returns(bytes32)\n {\n bytes32 result;\n\n if (interfaceHash == ERC777_TOKENS_RECIPIENT_INTERFACE_HASH && addr == address(this)) {\n result = ERC1820_ACCEPT_MAGIC;\n }\n\n return result;\n }\n\n // ERC1271\n\n function isValidSignature(\n bytes32 messageHash,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), messageHash, signature)\n ? ERC1271_VALID_MESSAGE_HASH_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n function isValidSignature(\n bytes calldata message,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), message, signature)\n ? ERC1271_VALID_MESSAGE_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n // external functions (pure)\n\n // ERC721\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC721Received.selector;\n }\n\n // ERC1155\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC1155Received.selector;\n }\n\n // ERC777\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n )\n external\n pure\n {}\n}\n" + }, + "src/personal/PersonalAccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/account/AccountImplementationV1.sol\";\n\n\n/**\n * @title Personal account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\n\n /**\n * @dev Public constructor\n */\n constructor() public AccountImplementationV1() {}\n}\n" + }, + "src/common/account/mocks/AccountImplementationV1Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountImplementationV1.sol\";\n\n\n/**\n * @title Account implementation mock (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1Mock is AccountImplementationV1 {\n /**\n * @dev Public constructor\n * @param registry_ account registry address\n */\n constructor(\n address registry_\n )\n public\n AccountImplementationV1()\n {\n registry = registry_;\n }\n}\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/fantomTest/GatewayV2.json b/deployments/fantomTest/GatewayV2.json new file mode 100644 index 00000000..886ce0a8 --- /dev/null +++ b/deployments/fantomTest/GatewayV2.json @@ -0,0 +1,926 @@ +{ + "address": "0xBEd52610518788B931f7825301909e7616273d47", + "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": "0xcce8ae16dd3a0eff4e5748005473002ebb2e0a758c02524290e52d85cf91652a", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "contractAddress": null, + "transactionIndex": 0, + "gasUsed": "2826126", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x000035fc00000b236a53449ced434079a5bad4673f8243fdd7603335e72e87d2", + "transactionHash": "0xcce8ae16dd3a0eff4e5748005473002ebb2e0a758c02524290e52d85cf91652a", + "logs": [], + "blockNumber": 11150337, + "cumulativeGasUsed": "2826126", + "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 \",\"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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 ", + "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" + } + } + } +} \ No newline at end of file diff --git a/deployments/fantomTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json b/deployments/fantomTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json new file mode 100644 index 00000000..fa380d29 --- /dev/null +++ b/deployments/fantomTest/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json @@ -0,0 +1,142 @@ +{ + "language": "Solidity", + "sources": { + "src/payments/PaymentRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./PaymentDepositAccount.sol\";\n\n\n/**\n * @title Payment registry\n *\n * @notice A registry for payment and payment channels\n *\n * @dev the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message.\n * Process will be rejected when any of senders channels will be committed.\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct Deposit {\n address account;\n mapping(address => uint256) withdrawnAmount;\n mapping(address => uint256) exitLockedUntil;\n }\n\n struct PaymentChannel {\n uint256 committedAmount;\n }\n\n struct DepositWithdrawal {\n address owner;\n address token;\n uint256 amount;\n }\n\n struct PaymentChannelCommit {\n address sender;\n address recipient;\n address token;\n bytes32 uid;\n uint256 blockNumber;\n uint256 amount;\n }\n\n uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;\n\n bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(\n \"DepositWithdrawal(address owner,address token,uint256 amount)\"\n );\n bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(\n \"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n uint256 public depositExitLockPeriod;\n\n mapping(address => Deposit) private deposits;\n mapping(bytes32 => PaymentChannel) private paymentChannels;\n\n // events\n\n /**\n * @dev Emitted when the deposit account is deployed\n * @param depositAccount deposit account address\n * @param owner owner address\n */\n event DepositAccountDeployed(\n address depositAccount,\n address owner\n );\n\n /**\n * @dev Emitted when the deposit exist is requested\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param lockedUntil deposit exist locked util time\n */\n event DepositExitRequested(\n address depositAccount,\n address owner,\n address token,\n uint256 lockedUntil\n );\n\n /**\n * @dev Emitted when the deposit exist is completed\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount deposit exist amount\n */\n event DepositExitCompleted(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the deposit exist is rejected\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n */\n event DepositExitRejected(\n address depositAccount,\n address owner,\n address token\n );\n\n /**\n * @dev Emitted when the deposit has been withdrawn\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount withdrawn amount\n */\n event DepositWithdrawn(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment channel has been committed\n * @param hash channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @param amount committed amount\n */\n event PaymentChannelCommitted(\n bytes32 hash,\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentWithdrawn(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been deposited\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentDeposited(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn and deposited (split)\n * @param channelHash channel hash\n * @param totalValue payment total value\n * @param depositValue payment deposited value\n */\n event PaymentSplit(\n bytes32 channelHash,\n uint256 totalValue,\n uint256 depositValue\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initialize `PaymentRegistry` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n * @param depositExitLockPeriod_ deposit exit lock period\n * @param guardians_ array of guardians addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_,\n uint256 depositExitLockPeriod_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n if (depositExitLockPeriod_ == 0) {\n depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;\n } else {\n depositExitLockPeriod = depositExitLockPeriod_;\n }\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Deploys deposit account\n * @param owner owner address\n */\n function deployDepositAccount(\n address owner\n )\n external\n {\n _deployDepositAccount(owner);\n }\n\n /**\n * @notice Requests deposit exit\n * @param token token address\n */\n function requestDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil == 0,\n \"PaymentRegistry: deposit exit already requested\"\n );\n\n _deployDepositAccount(owner);\n\n // solhint-disable-next-line not-rely-on-time\n lockedUntil = now.add(depositExitLockPeriod);\n\n deposits[owner].exitLockedUntil[token] = lockedUntil;\n\n emit DepositExitRequested(\n deposits[owner].account,\n owner,\n token,\n lockedUntil\n );\n }\n\n /**\n * @notice Processes deposit exit\n * @param token token address\n */\n function processDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil != 0,\n \"PaymentRegistry: deposit exit not requested\"\n );\n\n require(\n // solhint-disable-next-line not-rely-on-time\n lockedUntil <= now,\n \"PaymentRegistry: deposit exit locked\"\n );\n\n deposits[owner].exitLockedUntil[token] = 0;\n\n address depositAccount = deposits[owner].account;\n uint256 depositValue;\n\n if (token == address(0)) {\n depositValue = depositAccount.balance;\n } else {\n depositValue = ERC20Token(token).balanceOf(depositAccount);\n }\n\n _transferFromDeposit(\n depositAccount,\n owner,\n token,\n depositValue\n );\n\n emit DepositExitCompleted(\n depositAccount,\n owner,\n token,\n depositValue\n );\n }\n\n /**\n * @notice Withdraws deposit\n * @param token token address\n * @param amount amount to withdraw\n * @param guardianSignature guardian signature\n */\n function withdrawDeposit(\n address token,\n uint256 amount,\n bytes calldata guardianSignature\n )\n external\n {\n address owner = _getContextAccount();\n uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);\n\n require(\n value > 0,\n \"PaymentRegistry: invalid amount\"\n );\n\n bytes32 messageHash = _hashDepositWithdrawal(\n owner,\n token,\n amount\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n deposits[owner].withdrawnAmount[token] = amount;\n\n _verifyDepositExitOrDeployAccount(owner, token);\n\n _transferFromDeposit(\n deposits[owner].account,\n owner,\n token,\n value\n );\n\n emit DepositWithdrawn(\n deposits[owner].account,\n owner,\n token,\n amount\n );\n }\n\n /**\n * @notice Commits payment channel and withdraw payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndWithdraw(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue\n );\n\n emit PaymentWithdrawn(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel and deposit payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndDeposit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(recipient),\n token,\n paymentValue\n );\n\n emit PaymentDeposited(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel, withdraws and deposits (split) payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param depositPaymentValue amount to deposit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndSplit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n uint256 depositPaymentValue,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferSplitFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue,\n depositPaymentValue\n );\n\n emit PaymentSplit(hash, paymentValue, depositPaymentValue);\n }\n\n // external functions (views)\n\n /**\n * @notice Computes deposit account address\n * @param owner owner address\n * @return deposit account address\n */\n function computeDepositAccountAddress(\n address owner\n )\n external\n view\n returns (address)\n {\n return _computeDepositAccountAddress(owner);\n }\n\n /**\n * @notice Checks if deposit account is deployed\n * @param owner owner address\n * @return true when deposit account is deployed\n */\n function isDepositAccountDeployed(\n address owner\n )\n external\n view\n returns (bool)\n {\n return deposits[owner].account != address(0);\n }\n\n /**\n * @notice Gets deposit exit locked until time\n * @param owner owner address\n * @param token token address\n * @return locked until time\n */\n function getDepositExitLockedUntil(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].exitLockedUntil[token];\n }\n\n /**\n * @notice Gets deposit withdrawn amount\n * @param owner owner address\n * @param token token address\n * @return withdrawn amount\n */\n function getDepositWithdrawnAmount(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].withdrawnAmount[token];\n }\n\n /**\n * @notice Gets payment channel committed amount\n * @param hash payment channel hash\n * @return committed amount\n */\n function getPaymentChannelCommittedAmount(\n bytes32 hash\n )\n external\n view\n returns (uint256)\n {\n return paymentChannels[hash].committedAmount;\n }\n\n // external functions (pure)\n\n /**\n * @notice Computes payment channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @return hash\n */\n function computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n external\n pure\n returns (bytes32)\n {\n return _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DepositWithdrawal` message payload\n * @param depositWithdrawal struct\n * @return hash\n */\n function hashDepositWithdrawal(\n DepositWithdrawal memory depositWithdrawal\n )\n public\n view\n returns (bytes32)\n {\n return _hashDepositWithdrawal(\n depositWithdrawal.owner,\n depositWithdrawal.token,\n depositWithdrawal.amount\n );\n }\n\n /**\n * @notice Hashes `PaymentChannelCommit` message payload\n * @param paymentChannelCommit struct\n * @return hash\n */\n function hashPaymentChannelCommit(\n PaymentChannelCommit memory paymentChannelCommit\n )\n public\n view\n returns (bytes32)\n {\n return _hashPaymentChannelCommit(\n paymentChannelCommit.sender,\n paymentChannelCommit.recipient,\n paymentChannelCommit.token,\n paymentChannelCommit.uid,\n paymentChannelCommit.blockNumber,\n paymentChannelCommit.amount\n );\n }\n\n // private functions\n\n function _deployDepositAccount(\n address owner\n )\n private\n {\n if (deposits[owner].account == address(0)) {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());\n\n emit DepositAccountDeployed(\n deposits[owner].account,\n owner\n );\n }\n }\n\n function _verifyDepositExitOrDeployAccount(\n address owner,\n address token\n )\n private\n {\n if (deposits[owner].exitLockedUntil[token] > 0) {\n deposits[owner].exitLockedUntil[token] = 0;\n\n emit DepositExitRejected(\n deposits[owner].account,\n owner,\n token\n );\n } else {\n _deployDepositAccount(owner);\n }\n }\n\n function _commitPaymentChannel(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes memory senderSignature,\n bytes memory guardianSignature\n )\n private\n returns (bytes32 hash, address depositAccount, uint256 paymentValue)\n {\n bytes32 messageHash = _hashPaymentChannelCommit(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n );\n\n if (senderSignature.length == 0) {\n require(\n externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),\n \"PaymentRegistry: invalid guardian signature\"\n );\n } else {\n address signer = messageHash.recoverAddress(senderSignature);\n\n if (sender != signer) {\n require(\n personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||\n externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),\n \"PaymentRegistry: invalid sender signature\"\n );\n }\n }\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n hash = _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n\n /// @dev calc payment value\n paymentValue = amount.sub(paymentChannels[hash].committedAmount);\n\n require(\n paymentValue != 0,\n \"PaymentRegistry: invalid payment value\"\n );\n\n paymentChannels[hash].committedAmount = amount;\n\n _verifyDepositExitOrDeployAccount(sender, token);\n\n depositAccount = deposits[sender].account;\n\n emit PaymentChannelCommitted(\n hash,\n sender,\n recipient,\n token,\n uid,\n amount\n );\n\n return (hash, depositAccount, paymentValue);\n }\n\n function _transferFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 value\n )\n private\n {\n if (token == address(0)) {\n PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n to,\n value,\n new bytes(0)\n );\n } else {\n bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n token,\n 0,\n abi.encodeWithSelector(\n ERC20Token(token).transfer.selector,\n to,\n value\n )\n );\n\n if (response.length > 0) {\n require(\n abi.decode(response, (bool)),\n \"PaymentRegistry: ERC20Token transfer reverted\"\n );\n }\n }\n }\n\n function _transferSplitFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 paymentValue,\n uint256 depositValue\n )\n private\n {\n require(\n depositValue > 0,\n \"PaymentRegistry: invalid deposit value\"\n );\n\n uint256 withdrawValue = paymentValue.sub(depositValue);\n\n require(\n withdrawValue > 0,\n \"PaymentRegistry: invalid withdraw value\"\n );\n\n _transferFromDeposit(\n depositAccount,\n to,\n token,\n withdrawValue\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(to),\n token,\n depositValue\n );\n }\n\n // private functions (views)\n\n function _computeDepositAccountAddress(\n address owner\n )\n private\n view\n returns (address)\n {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n bytes memory creationCode = type(PaymentDepositAccount).creationCode;\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 function _hashDepositWithdrawal(\n address owner,\n address token,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(\n owner,\n token,\n amount\n ));\n }\n\n function _hashPaymentChannelCommit(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n ));\n }\n\n // private functions (pure)\n\n function _computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n private\n pure\n returns (bytes32)\n {\n return keccak256(\n abi.encodePacked(\n sender,\n recipient,\n token,\n uid\n )\n );\n }\n}\n" + }, + "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ław Głogowski \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" + }, + "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" + }, + "src/common/libs/SafeMathLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n" + }, + "src/common/lifecycle/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski \n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n" + }, + "src/common/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ław Głogowski \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" + }, + "src/common/token/ERC20Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n" + }, + "src/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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "src/gateway/GatewayRecipient.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n" + }, + "src/payments/PaymentDepositAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/access/Controlled.sol\";\n\n\n/**\n * @title Payment deposit account\n *\n * @dev Simple account contract with only one method - `executeTransaction`\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentDepositAccount is Controlled {\n /**\n * @dev Public constructor\n */\n constructor() public payable Controlled() {}\n\n /**\n * @notice Allow receives\n */\n receive()\n external\n payable\n {\n //\n }\n\n // external functions\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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \n */\ncontract AccountBase {\n address public registry;\n}\n" + }, + "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" + }, + "src/common/libs/BytesLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski \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" + }, + "src/tokens/WrappedWeiToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski \n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n" + }, + "src/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 \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" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.12;\r\npragma experimental ABIEncoderV2;\r\n\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/**\r\n * @title Gateway\r\n *\r\n * @notice GSN replacement\r\n *\r\n * @author Stanisław Głogowski \r\n */\r\ncontract Gateway is Initializable, SignatureValidator {\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\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 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 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 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 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 // 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}" + }, + "src/ens/ENSController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./resolvers/ENSPubKeyResolver.sol\";\nimport \"./resolvers/ENSTextResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n\n/**\n * @title ENS controller\n *\n * @notice ENS subnode registrar\n *\n * @dev The process of adding root node consists of 3 steps:\n * 1. `submitNode` - should be called from ENS node owner,\n * 2. Change ENS node owner in ENS registry to ENS controller,\n * 3. `verifyNode` - should be called from previous ENS node owner,\n *\n * To register sub node, `msg.sender` need to send valid signature from one of guardian key.\n * Once registration is complete `msg.sender` becoming both node owner and `addr` record value.\n *\n * After registration sub node cannot be replaced.\n *\n * @author Stanisław Głogowski \n */\ncontract ENSController is Guarded, Initializable, SignatureValidator, GatewayRecipient, ENSAddressResolver, ENSNameResolver, ENSPubKeyResolver, ENSTextResolver {\n struct SubNodeRegistration {\n address account;\n bytes32 node;\n bytes32 label;\n }\n\n bytes4 private constant INTERFACE_META_ID = bytes4(keccak256(abi.encodePacked(\"supportsInterface(bytes4)\")));\n\n bytes32 private constant HASH_PREFIX_SUB_NODE_REGISTRATION = keccak256(\n \"SubNodeRegistration(address account,bytes32 node,bytes32 label)\"\n );\n\n ENSRegistry public registry;\n\n mapping(bytes32 => address) public nodeOwners;\n\n // events\n\n /**\n * @dev Emitted when new node is submitted\n * @param node node name hash\n * @param owner owner address\n */\n event NodeSubmitted(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when the existing owner is verified\n * @param node node name hash\n */\n event NodeVerified(\n bytes32 node\n );\n\n /**\n * @dev Emitted when new node is released\n * @param node node name hash\n * @param owner owner address\n */\n event NodeReleased(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when ENS registry address is changed\n * @param registry registry address\n */\n event RegistryChanged(\n address registry\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Guarded() Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSController` contract\n * @param registry_ ENS registry address\n * @param gateway_ gateway address\n */\n function initialize(\n ENSRegistry registry_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n registry = registry_;\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Sets registry\n * @param registry_ registry address\n */\n function setRegistry(\n ENSRegistry registry_\n )\n external\n onlyGuardian\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n require(\n registry_ != registry,\n \"ENSController: registry already set\"\n );\n\n registry = registry_;\n\n emit RegistryChanged(\n address(registry)\n );\n }\n\n /**\n * @notice Submits node\n * @dev Should be called from the current ENS node owner\n * @param node node name hash\n */\n function submitNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == address(0),\n \"ENSController: node already submitted\"\n );\n\n require(\n registry.owner(node) == owner,\n \"ENSController: invalid ens node owner\"\n );\n\n nodeOwners[node] = owner;\n\n emit NodeSubmitted(node, owner);\n }\n\n /**\n * @notice Verifies node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function verifyNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n require(\n registry.owner(node) == address(this),\n \"ENSController: invalid ens node owner\"\n );\n\n _setAddr(node, address(this));\n\n registry.setResolver(node, address(this));\n\n emit NodeVerified(node);\n }\n\n /**\n * @notice Releases node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function releaseNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(this),\n \"ENSController: node doesn't exist\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n registry.setOwner(node, owner);\n\n delete nodeOwners[node];\n\n emit NodeReleased(node, owner);\n }\n\n /**\n * @notice Sync address\n * @param node node name hash\n */\n function syncAddr(\n bytes32 node\n )\n external\n {\n address account = _getContextAccount();\n\n require(\n account == registry.owner(node),\n \"ENSController: caller is not the node owner\"\n );\n\n require(\n registry.resolver(node) == address(this),\n \"ENSController: invalid node resolver\"\n );\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already in sync\"\n );\n\n _setAddr(node, account);\n }\n\n /**\n * @notice Registers sub node\n * @param node node name hash\n * @param label label hash\n * @param guardianSignature guardian signature\n */\n function registerSubNode(\n bytes32 node,\n bytes32 label,\n bytes calldata guardianSignature\n )\n external\n {\n address account = _getContextAccount();\n\n bytes32 messageHash = _hashSubNodeRegistration(\n account,\n node,\n label\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"ENSController: invalid guardian signature\"\n );\n\n bytes32 subNode = keccak256(\n abi.encodePacked(\n node,\n label\n )\n );\n\n require(\n _addr(node) == address(this),\n \"ENSController: invalid node\"\n );\n\n require(\n _addr(subNode) == address(0),\n \"ENSController: label already taken\"\n );\n\n registry.setSubnodeRecord(node, label, address(this), address(this), 0);\n registry.setOwner(subNode, account);\n\n _setAddr(subNode, account);\n }\n\n // external functions (pure)\n function supportsInterface(\n bytes4 interfaceID\n )\n external\n pure\n returns(bool)\n {\n return interfaceID == INTERFACE_META_ID ||\n interfaceID == INTERFACE_ADDR_ID ||\n interfaceID == INTERFACE_ADDRESS_ID ||\n interfaceID == INTERFACE_NAME_ID ||\n interfaceID == INTERFACE_PUB_KEY_ID ||\n interfaceID == INTERFACE_TEXT_ID;\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `SubNodeRegistration` message payload\n * @param subNodeRegistration struct\n * @return hash\n */\n function hashSubNodeRegistration(\n SubNodeRegistration memory subNodeRegistration\n )\n public\n view\n returns (bytes32)\n {\n return _hashSubNodeRegistration(\n subNodeRegistration.account,\n subNodeRegistration.node,\n subNodeRegistration.label\n );\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n override\n view\n returns (bool)\n {\n return registry.owner(node) == _getContextAccount();\n }\n\n // private functions (views)\n\n function _hashSubNodeRegistration(\n address account,\n bytes32 node,\n bytes32 label\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_SUB_NODE_REGISTRATION, abi.encodePacked(\n account,\n node,\n label\n ));\n }\n}\n" + }, + "src/ens/resolvers/ENSAddressResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract address resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/AddrResolver.sol\n */\nabstract contract ENSAddressResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_ADDR_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32)\")));\n bytes4 internal constant INTERFACE_ADDRESS_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32,uint)\")));\n\n uint internal constant COIN_TYPE_ETH = 60;\n\n mapping(bytes32 => mapping(uint => bytes)) internal resolverAddresses;\n\n // events\n\n event AddrChanged(\n bytes32 indexed node,\n address addr\n );\n\n event AddressChanged(\n bytes32 indexed node,\n uint coinType,\n bytes newAddress\n );\n\n // external functions\n\n function setAddr(\n bytes32 node,\n address addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, addr_);\n }\n\n function setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, coinType, addr_);\n }\n\n // external functions (views)\n\n function addr(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return _addr(node);\n }\n\n function addr(\n bytes32 node,\n uint coinType\n )\n external\n view\n returns (bytes memory)\n {\n return resolverAddresses[node][coinType];\n }\n\n // internal functions\n\n function _setAddr(\n bytes32 node,\n address addr_\n )\n internal\n {\n _setAddr(node, COIN_TYPE_ETH, _addressToBytes(addr_));\n }\n\n function _setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n internal\n {\n emit AddressChanged(node, coinType, addr_);\n\n if(coinType == COIN_TYPE_ETH) {\n emit AddrChanged(node, _bytesToAddress(addr_));\n }\n\n resolverAddresses[node][coinType] = addr_;\n }\n\n // internal functions (views)\n\n function _addr(\n bytes32 node\n )\n internal\n view\n returns (address)\n {\n address result;\n\n bytes memory addr_ = resolverAddresses[node][COIN_TYPE_ETH];\n\n if (addr_.length > 0) {\n result = _bytesToAddress(addr_);\n }\n\n return result;\n }\n\n // private function (pure)\n\n function _bytesToAddress(\n bytes memory data\n )\n private\n pure\n returns(address payable)\n {\n address payable result;\n\n require(data.length == 20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 32)), exp(256, 12))\n }\n\n return result;\n }\n\n function _addressToBytes(\n address addr_\n )\n private\n pure\n returns(bytes memory)\n {\n bytes memory result = new bytes(20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(add(result, 32), mul(addr_, exp(256, 12)))\n }\n\n return result;\n }\n}\n" + }, + "src/ens/resolvers/ENSNameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract name resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/NameResolver.sol\n */\nabstract contract ENSNameResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_NAME_ID = bytes4(keccak256(abi.encodePacked(\"name(bytes32)\")));\n\n mapping(bytes32 => string) internal resolverNames;\n\n // events\n\n event NameChanged(\n bytes32 indexed node,\n string name\n );\n\n // external functions\n\n function setName(\n bytes32 node,\n string calldata name\n )\n external\n onlyNodeOwner(node)\n {\n resolverNames[node] = name;\n\n emit NameChanged(node, name);\n }\n\n // external functions (views)\n\n function name(\n bytes32 node\n )\n external\n view\n returns (string memory)\n {\n return resolverNames[node];\n }\n}\n" + }, + "src/ens/resolvers/ENSPubKeyResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract pub key resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/PubkeyResolver.sol\n */\nabstract contract ENSPubKeyResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_PUB_KEY_ID = bytes4(keccak256(abi.encodePacked(\"pubkey(bytes32)\")));\n\n struct PubKey {\n bytes32 x;\n bytes32 y;\n }\n\n mapping(bytes32 => PubKey) internal resolverPubKeys;\n\n // events\n\n event PubkeyChanged(\n bytes32 indexed node,\n bytes32 x,\n bytes32 y\n );\n\n // external functions (views)\n\n function setPubkey(\n bytes32 node,\n bytes32 x,\n bytes32 y\n )\n external\n onlyNodeOwner(node)\n {\n resolverPubKeys[node] = PubKey(x, y);\n\n emit PubkeyChanged(node, x, y);\n }\n\n // external functions (views)\n\n function pubkey(\n bytes32 node\n )\n external\n view\n returns (bytes32 x, bytes32 y)\n {\n return (resolverPubKeys[node].x, resolverPubKeys[node].y);\n }\n}\n" + }, + "src/ens/resolvers/ENSTextResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract text resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/TextResolver.sol\n */\nabstract contract ENSTextResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_TEXT_ID = bytes4(keccak256(abi.encodePacked(\"text(bytes32,string)\")));\n\n mapping(bytes32 => mapping(string => string)) internal resolverTexts;\n\n // events\n\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key\n );\n\n // external functions (views)\n\n function setText(\n bytes32 node,\n string calldata key,\n string calldata value\n )\n external\n onlyNodeOwner(node)\n {\n resolverTexts[node][key] = value;\n\n emit TextChanged(node, key, key);\n }\n\n // external functions (views)\n\n function text(\n bytes32 node,\n string calldata key\n )\n external\n view\n returns (string memory)\n {\n return resolverTexts[node][key];\n }\n}\n" + }, + "src/ens/ENSRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS registry\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\n */\ncontract ENSRegistry {\n struct Record {\n address owner;\n address resolver;\n uint64 ttl;\n }\n\n mapping (bytes32 => Record) private records;\n mapping (address => mapping(address => bool)) private operators;\n\n // events\n\n event NewOwner(\n bytes32 indexed node,\n bytes32 indexed label,\n address owner\n );\n\n event Transfer(\n bytes32 indexed node,\n address owner\n );\n\n event NewResolver(\n bytes32 indexed node,\n address resolver\n );\n\n event NewTTL(\n bytes32 indexed node,\n uint64 ttl\n );\n\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n // modifiers\n\n modifier authorised(\n bytes32 node\n )\n {\n address owner = records[node].owner;\n\n require(\n owner == msg.sender || operators[owner][msg.sender],\n \"ENSRegistry: reverted by authorised modifier\"\n );\n\n _;\n }\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n {\n // solhint-disable-next-line avoid-tx-origin\n records[0x0].owner = tx.origin;\n }\n\n // external functions\n\n function setRecord(\n bytes32 node,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n setOwner(node, owner_);\n\n _setResolverAndTTL(node, resolver_, ttl_);\n }\n\n function setTTL(\n bytes32 node,\n uint64 ttl_\n )\n external\n authorised(node)\n {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n bytes32 subNode = setSubnodeOwner(node, label, owner_);\n\n _setResolverAndTTL(subNode, resolver_, ttl_);\n }\n\n function setApprovalForAll(\n address operator,\n bool approved\n )\n external\n {\n operators[msg.sender][operator] = approved;\n\n emit ApprovalForAll(\n msg.sender,\n operator,\n approved\n );\n }\n\n // external functions (views)\n\n function owner(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n address addr = records[node].owner;\n\n if (addr == address(this)) {\n return address(0x0);\n }\n\n return addr;\n }\n\n function resolver(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return records[node].resolver;\n }\n\n function ttl(\n bytes32 node\n )\n external\n view\n returns (uint64)\n {\n return records[node].ttl;\n }\n\n function recordExists(\n bytes32 node\n )\n external\n view\n returns (bool)\n {\n return records[node].owner != address(0x0);\n }\n\n function isApprovedForAll(\n address owner_,\n address operator\n )\n external\n view\n returns (bool)\n {\n return operators[owner_][operator];\n }\n\n // public functions\n\n function setOwner(\n bytes32 node,\n address owner_\n )\n public\n authorised(node)\n {\n records[node].owner = owner_;\n\n emit Transfer(node, owner_);\n }\n\n function setResolver(\n bytes32 node,\n address resolver_\n )\n public\n authorised(node)\n {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner_\n )\n public\n authorised(node)\n returns(bytes32)\n {\n bytes32 subNode = keccak256(abi.encodePacked(node, label));\n\n records[subNode].owner = owner_;\n\n emit NewOwner(node, label, owner_);\n\n return subNode;\n }\n\n // private functions\n\n function _setResolverAndTTL(\n bytes32 node,\n address resolver_,\n uint64 ttl_\n )\n private\n {\n if (resolver_ != records[node].resolver) {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n if (ttl_ != records[node].ttl) {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n }\n}\n" + }, + "src/ens/resolvers/ENSAbstractResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS abstract resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/ResolverBase.sol\n */\nabstract contract ENSAbstractResolver {\n // modifiers\n\n modifier onlyNodeOwner(bytes32 node)\n {\n require(\n _isNodeOwner(node),\n \"ENSAbstractResolver: reverted by onlyNodeOwner modifier\"\n );\n\n _;\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n virtual\n view\n returns (bool);\n}\n" + }, + "src/ens/ENSReverseRegistrar.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/AddressLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS reverse registrar\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\n */\ncontract ENSReverseRegistrar is Initializable {\n using AddressLib for address;\n\n // namehash('addr.reverse')\n bytes32 public constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n ENSRegistry public registry;\n ENSNameResolver public resolver;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSReverseRegistrar` contract\n * @param registry_ ENS registry address\n * @param resolver_ ENS name resolver address\n */\n function initialize(\n ENSRegistry registry_,\n ENSNameResolver resolver_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n resolver = resolver_;\n }\n\n // external functions\n\n function claim(\n address owner\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, address(0));\n }\n\n function claimWithResolver(\n address owner,\n address resolver_\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, resolver_);\n }\n\n function setName(\n string memory name\n )\n public\n returns (bytes32)\n {\n bytes32 node = _claimWithResolver(address(this), address(resolver));\n\n resolver.setName(node, name);\n\n return node;\n }\n\n // external functions (pure)\n\n function node(\n address addr_\n )\n external\n pure\n returns (bytes32)\n {\n return keccak256(abi.encodePacked(ADDR_REVERSE_NODE, addr_.toSha3Hash()));\n }\n\n // private functions\n\n function _claimWithResolver(\n address owner,\n address resolver_\n )\n private\n returns (bytes32)\n {\n bytes32 label = address(msg.sender).toSha3Hash();\n bytes32 node_ = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n address currentOwner = registry.owner(node_);\n\n if (resolver_ != address(0x0) && resolver_ != registry.resolver(node_)) {\n if (currentOwner != address(this)) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this));\n currentOwner = address(this);\n }\n\n registry.setResolver(node_, resolver_);\n }\n\n // Update the owner if required\n if (currentOwner != owner) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);\n }\n\n return node_;\n }\n}\n" + }, + "src/common/libs/AddressLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Address library\n */\nlibrary AddressLib {\n /**\n * @notice Converts address into sha3 hash\n * @param self address\n * @return sha3 hash\n */\n function toSha3Hash(\n address self\n )\n internal\n pure\n returns (bytes32)\n {\n bytes32 result;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000\n\n for { let i := 40 } gt(i, 0) { } {\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n }\n\n result := keccak256(0, 40)\n }\n\n return result;\n }\n}\n" + }, + "src/ens/ENSHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS helper\n *\n * @author Stanisław Głogowski \n */\ncontract ENSHelper is Initializable {\n ENSRegistry public registry;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSLookupHelper` contract\n * @param registry_ ENS registry address\n */\n function initialize(\n ENSRegistry registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n /**\n * @notice Gets nodes addresses\n * @param nodes array of nodes\n * @return nodes addresses\n */\n function getAddresses(\n bytes32[] memory nodes\n )\n external\n view\n returns (address[] memory)\n {\n uint nodesLen = nodes.length;\n address[] memory result = new address[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getAddress(nodes[i]);\n }\n\n return result;\n }\n\n /**\n * @notice Gets nodes names\n * @param nodes array of nodes\n * @return nodes names\n */\n function getNames(\n bytes32[] memory nodes\n )\n external\n view\n returns (string[] memory)\n {\n uint nodesLen = nodes.length;\n string[] memory result = new string[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getName(nodes[i]);\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getAddress(\n bytes32 node\n )\n private\n view\n returns (address)\n {\n address result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSAddressResolver(resolver).addr(node) returns (address addr) {\n result = addr;\n } catch {\n //\n }\n }\n\n return result;\n }\n\n function _getName(\n bytes32 node\n )\n private\n view\n returns (string memory)\n {\n string memory result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSNameResolver(resolver).name(node) returns (string memory name) {\n result = name;\n } catch {\n //\n }\n }\n\n return result;\n }\n}\n" + }, + "src/common/account/AccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../lifecycle/Initializable.sol\";\nimport \"./AccountBase.sol\";\nimport \"./AccountRegistry.sol\";\n\n\n/**\n * @title Account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1 is Initializable, AccountBase {\n bytes32 constant private ERC777_TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(abi.encodePacked(\"ERC777TokensRecipient\"));\n bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n bytes4 constant private ERC1271_VALID_MESSAGE_HASH_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes32,bytes)\")));\n bytes4 constant private ERC1271_VALID_MESSAGE_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes,bytes)\")));\n bytes4 constant private ERC1271_INVALID_SIGNATURE = 0xffffffff;\n\n /**\n * @dev Internal constructor\n */\n constructor() internal Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `AccountImplementation` contract\n * @param registry_ registry address\n */\n function initialize(\n address registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n // ERC1820\n\n function canImplementInterfaceForAddress(\n bytes32 interfaceHash,\n address addr\n )\n external\n view\n returns(bytes32)\n {\n bytes32 result;\n\n if (interfaceHash == ERC777_TOKENS_RECIPIENT_INTERFACE_HASH && addr == address(this)) {\n result = ERC1820_ACCEPT_MAGIC;\n }\n\n return result;\n }\n\n // ERC1271\n\n function isValidSignature(\n bytes32 messageHash,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), messageHash, signature)\n ? ERC1271_VALID_MESSAGE_HASH_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n function isValidSignature(\n bytes calldata message,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), message, signature)\n ? ERC1271_VALID_MESSAGE_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n // external functions (pure)\n\n // ERC721\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC721Received.selector;\n }\n\n // ERC1155\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC1155Received.selector;\n }\n\n // ERC777\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n )\n external\n pure\n {}\n}\n" + }, + "src/personal/PersonalAccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/account/AccountImplementationV1.sol\";\n\n\n/**\n * @title Personal account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\n\n /**\n * @dev Public constructor\n */\n constructor() public AccountImplementationV1() {}\n}\n" + }, + "src/common/account/mocks/AccountImplementationV1Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountImplementationV1.sol\";\n\n\n/**\n * @title Account implementation mock (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1Mock is AccountImplementationV1 {\n /**\n * @dev Public constructor\n * @param registry_ account registry address\n */\n constructor(\n address registry_\n )\n public\n AccountImplementationV1()\n {\n registry = registry_;\n }\n}\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/fuji/BalancesHelperV2.json b/deployments/fuji/BalancesHelperV2.json new file mode 100644 index 00000000..e87f96bf --- /dev/null +++ b/deployments/fuji/BalancesHelperV2.json @@ -0,0 +1,160 @@ +{ + "address": "0x13261B2b8674Cb855c408F3721281330ee16C66E", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "AccountZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getBalances", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getSuperfluidWrappedTokenBalances", + "outputs": [ + { + "internalType": "int256[]", + "name": "", + "type": "int256[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xc68d2e1d7e9921a4bcb5e02ac326ad5dd2c6ed1030c4ba1e2994fd0a63cf9742", + "receipt": { + "to": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7", + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "contractAddress": null, + "transactionIndex": 2, + "gasUsed": "964203", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xd92d221b742fb1da7fa3ee654974362eb8f6c4a2d7141362d71c7343d61ed320", + "transactionHash": "0xc68d2e1d7e9921a4bcb5e02ac326ad5dd2c6ed1030c4ba1e2994fd0a63cf9742", + "logs": [], + "blockNumber": 14561641, + "cumulativeGasUsed": "1123860", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "893c7c8579088197a1acbd2718e7b759", + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"AccountZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getSuperfluidWrappedTokenBalances\",\"outputs\":[{\"internalType\":\"int256[]\",\"name\":\"\",\"type\":\"int256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"AccountZeroAddress(address,address)\":[{\"notice\":\"Custom errors to handle address(0)\"}]},\"kind\":\"user\",\"methods\":{\"getBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple ERC20 tokens.\"},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple Wrapped Super Tokens.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/common/helpers/BalancesHelperV2.sol\":\"BalancesHelperV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0x6ebf1944ab804b8660eb6fc52f9fe84588cee01c2566a69023e59497e7d27f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperAgreement.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperfluidToken } from \\\"./ISuperfluidToken.sol\\\";\\n\\n/**\\n * @title Super agreement interface\\n * @author Superfluid\\n */\\ninterface ISuperAgreement {\\n\\n /**\\n * @dev Get the type of the agreement class\\n */\\n function agreementType() external view returns (bytes32);\\n\\n /**\\n * @dev Calculate the real-time balance for the account of this agreement class\\n * @param account Account the state belongs to\\n * @param time Time used for the calculation\\n * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement\\n * @return deposit Account deposit amount of this agreement\\n * @return owedDeposit Account owed deposit amount of this agreement\\n */\\n function realtimeBalanceOf(\\n ISuperfluidToken token,\\n address account,\\n uint256 time\\n )\\n external\\n view\\n returns (\\n int256 dynamicBalance,\\n uint256 deposit,\\n uint256 owedDeposit\\n );\\n\\n}\\n\",\"keccak256\":\"0xc3a6a907245116bcecc70fe4b207454012e8ce4fa190228fb8bbe39e0b1bc5cf\",\"license\":\"AGPLv3\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperAgreement } from \\\"./ISuperAgreement.sol\\\";\\n\\n\\n/**\\n * @title Superfluid token interface\\n * @author Superfluid\\n */\\ninterface ISuperfluidToken {\\n\\n /**************************************************************************\\n * Basic information\\n *************************************************************************/\\n\\n /**\\n * @dev Get superfluid host contract address\\n */\\n function getHost() external view returns(address host);\\n\\n /**\\n * @dev Encoded liquidation type data mainly used for handling stack to deep errors\\n *\\n * Note:\\n * - version: 1\\n * - liquidationType key:\\n * - 0 = reward account receives reward (PIC period)\\n * - 1 = liquidator account receives reward (Pleb period)\\n * - 2 = liquidator account receives reward (Pirate period/bailout)\\n */\\n struct LiquidationTypeData {\\n uint256 version;\\n uint8 liquidationType;\\n }\\n\\n /**************************************************************************\\n * Real-time balance functions\\n *************************************************************************/\\n\\n /**\\n * @dev Calculate the real balance of a user, taking in consideration all agreements of the account\\n * @param account for the query\\n * @param timestamp Time of balance\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOf(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit);\\n\\n /**\\n * @notice Calculate the realtime balance given the current host.getNow() value\\n * @dev realtimeBalanceOf with timestamp equals to block timestamp\\n * @param account for the query\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOfNow(\\n address account\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit,\\n uint256 timestamp);\\n\\n /**\\n * @notice Check if account is critical\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is critical (should use future)\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCritical(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is critical now (current host.getNow())\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCriticalNow(\\n address account\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is solvent\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is solvent (should use future)\\n * @return isSolvent\\n */\\n function isAccountSolvent(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Check if account is solvent now\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @return isSolvent\\n */\\n function isAccountSolventNow(\\n address account\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Get a list of agreements that is active for the account\\n * @dev An active agreement is one that has state for the account\\n * @param account Account to query\\n * @return activeAgreements List of accounts that have non-zero states for the account\\n */\\n function getAccountActiveAgreements(address account)\\n external view\\n returns(ISuperAgreement[] memory activeAgreements);\\n\\n\\n /**************************************************************************\\n * Super Agreement hosting functions\\n *************************************************************************/\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function createAgreement(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement created event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementCreated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Get data of the agreement\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @return data Data of the agreement\\n */\\n function getAgreementData(\\n address agreementClass,\\n bytes32 id,\\n uint dataLength\\n )\\n external view\\n returns(bytes32[] memory data);\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function updateAgreementData(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement updated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementUpdated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Close the agreement\\n * @param id Agreement ID\\n */\\n function terminateAgreement(\\n bytes32 id,\\n uint dataLength\\n )\\n external;\\n /**\\n * @dev Agreement terminated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n */\\n event AgreementTerminated(\\n address indexed agreementClass,\\n bytes32 id\\n );\\n\\n /**\\n * @dev Update agreement state slot\\n * @param account Account to be updated\\n *\\n * NOTE\\n * - To clear the storage out, provide zero-ed array of intended length\\n */\\n function updateAgreementStateSlot(\\n address account,\\n uint256 slotId,\\n bytes32[] calldata slotData\\n )\\n external;\\n /**\\n * @dev Agreement account state updated event\\n * @param agreementClass Contract address of the agreement\\n * @param account Account updated\\n * @param slotId slot id of the agreement state\\n */\\n event AgreementStateUpdated(\\n address indexed agreementClass,\\n address indexed account,\\n uint256 slotId\\n );\\n\\n /**\\n * @dev Get data of the slot of the state of an agreement\\n * @param agreementClass Contract address of the agreement\\n * @param account Account to query\\n * @param slotId slot id of the state\\n * @param dataLength length of the state data\\n */\\n function getAgreementStateSlot(\\n address agreementClass,\\n address account,\\n uint256 slotId,\\n uint dataLength\\n )\\n external view\\n returns (bytes32[] memory slotData);\\n\\n /**\\n * @notice Settle balance from an account by the agreement\\n * @dev The agreement needs to make sure that the balance delta is balanced afterwards\\n * @param account Account to query.\\n * @param delta Amount of balance delta to be settled\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function settleBalance(\\n address account,\\n int256 delta\\n )\\n external;\\n\\n /**\\n * @dev Make liquidation payouts (v2)\\n * @param id Agreement ID\\n * @param liquidationTypeData Data regarding the version of the liquidation schema and the type\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount\\n * @param targetAccount Account of the stream sender\\n * @param rewardAmount The amount the reward recepient account will receive\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n *\\n * - If a bailout is required (bailoutAmount > 0)\\n * - the actual reward (single deposit) goes to the executor,\\n * - while the reward account becomes the bailout account\\n * - total bailout include: bailout amount + reward amount\\n * - the targetAccount will be bailed out\\n * - If a bailout is not required\\n * - the targetAccount will pay the rewardAmount\\n * - the liquidator (reward account in PIC period) will receive the rewardAmount\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function makeLiquidationPayoutsV2\\n (\\n bytes32 id,\\n bytes memory liquidationTypeData,\\n address liquidatorAccount,\\n bool useDefaultRewardAccount,\\n address targetAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta\\n ) external;\\n /**\\n * @dev Agreement liquidation event v2 (including agent account)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param targetAccount Account of the stream sender\\n * @param rewardAccount Account that collects the reward or bails out insolvent accounts\\n * @param rewardAmount The amount the reward recipient account balance should change by\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n * @param liquidationTypeData The encoded liquidation type data including the version (how to decode)\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if the agreement is liquidated during the PIC period\\n * - the rewardAccount will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount\\n * - the targetAccount will pay for the rewardAmount\\n * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent\\n * - the liquidatorAccount will get the rewardAmount (remaining deposit)\\n * - the targetAccount will pay for the rewardAmount\\n * - if the targetAccount is insolvent\\n * - the liquidatorAccount will get the rewardAmount (single deposit)\\n * - the rewardAccount will pay for both the rewardAmount and bailoutAmount\\n * - the targetAccount will receive the bailoutAmount\\n */\\n event AgreementLiquidatedV2(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed liquidatorAccount,\\n address indexed targetAccount,\\n address rewardAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta,\\n bytes liquidationTypeData\\n );\\n\\n /**************************************************************************\\n * Function modifiers for access control and parameter validations\\n *\\n * While they cannot be explicitly stated in function definitions, they are\\n * listed in function definition comments instead for clarity.\\n *\\n * NOTE: solidity-coverage not supporting it\\n *************************************************************************/\\n\\n /// @dev The msg.sender must be host contract\\n //modifier onlyHost() virtual;\\n\\n /// @dev The msg.sender must be a listed agreement.\\n //modifier onlyAgreement() virtual;\\n\\n /**************************************************************************\\n * DEPRECATED\\n *************************************************************************/\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param rewardAccount Account that collect the reward\\n * @param rewardAmount Amount of liquidation reward\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event AgreementLiquidated(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed rewardAccount,\\n uint256 rewardAmount\\n );\\n\\n /**\\n * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy)\\n * @param bailoutAccount Account that bailout the penalty account\\n * @param bailoutAmount Amount of account bailout\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event Bailout(\\n address indexed bailoutAccount,\\n uint256 bailoutAmount\\n );\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2)\\n * @param liquidatorAccount Account of the agent that performed the liquidation.\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param bondAccount Account that collect the reward or bailout accounts\\n * @param rewardAmount Amount of liquidation reward\\n * @param bailoutAmount Amount of liquidation bailouot\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if bailout is equal to 0, then\\n * - the bondAccount will get the rewardAmount,\\n * - the penaltyAccount will pay for the rewardAmount.\\n * - if bailout is larger than 0, then\\n * - the liquidatorAccount will get the rewardAmouont,\\n * - the bondAccount will pay for both the rewardAmount and bailoutAmount,\\n * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.\\n */\\n event AgreementLiquidatedBy(\\n address liquidatorAccount,\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed bondAccount,\\n uint256 rewardAmount,\\n uint256 bailoutAmount\\n );\\n}\\n\",\"keccak256\":\"0x9189eaba9e856cc4932ea29eeaf4e89a09448dde13860591691ec122856fdc75\",\"license\":\"AGPLv3\"},\"src/common/helpers/BalancesHelperV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\n// solhint-disable-next-line\\r\\npragma solidity 0.8.4;\\r\\n\\r\\n/// @title BalancesHelperV2\\r\\n/// @author Luke Wickens \\r\\n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\\r\\n\\r\\nimport {ISuperfluidToken} from \\\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\\\";\\r\\nimport {IERC20} from \\\"@openzeppelin/contracts/interfaces/IERC20.sol\\\";\\r\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\r\\n\\r\\ncontract BalancesHelperV2 {\\r\\n using Address for address;\\r\\n\\r\\n /// @notice Custom errors to handle address(0)\\r\\n error AccountZeroAddress(address account, address token);\\r\\n error TokenZeroAddress(address account, address token);\\r\\n\\r\\n constructor() {}\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple ERC20 tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getBalances(address[] calldata accounts, address[] calldata tokens)\\r\\n external\\r\\n view\\r\\n returns (uint256[] memory)\\r\\n {\\r\\n uint256[] memory result = new uint256[](\\r\\n accounts.length * tokens.length\\r\\n );\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getBalance(accounts[i], tokens[j]);\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getSuperfluidWrappedTokenBalances(\\r\\n address[] calldata accounts,\\r\\n address[] calldata tokens\\r\\n ) external view returns (int256[] memory) {\\r\\n int256[] memory result = new int256[](accounts.length * tokens.length);\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getSuperfluidWrappedTokenBalance(\\r\\n accounts[i],\\r\\n tokens[j]\\r\\n );\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// Private fuctions\\r\\n\\r\\n /// @notice Returns balance of account for an ERC20 token.\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return balance of account as uint256.\\r\\n\\r\\n function _getBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (uint256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\\r\\n );\\r\\n\\r\\n return abi.decode(returnedData, (uint256));\\r\\n }\\r\\n\\r\\n /// @notice Returns real balance of a user, taking into consideration all agreements of account\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return available balance of account as int256.\\r\\n\\r\\n function _getSuperfluidWrappedTokenBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (int256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(\\r\\n ISuperfluidToken(token).realtimeBalanceOfNow.selector,\\r\\n account\\r\\n )\\r\\n );\\r\\n\\r\\n (int256 availableBalance, , , ) = abi.decode(\\r\\n returnedData,\\r\\n (int256, uint256, uint256, uint256)\\r\\n );\\r\\n return availableBalance;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xee88323570149a5d9e569da056eaa089cf4baacfb3713a0dd282090b1d0847d2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061108a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "devdoc": { + "kind": "dev", + "methods": { + "getBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "AccountZeroAddress(address,address)": [ + { + "notice": "Custom errors to handle address(0)" + } + ] + }, + "kind": "user", + "methods": { + "getBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple ERC20 tokens." + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple Wrapped Super Tokens." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/fuji/GatewayV2.json b/deployments/fuji/GatewayV2.json new file mode 100644 index 00000000..1eb79d00 --- /dev/null +++ b/deployments/fuji/GatewayV2.json @@ -0,0 +1,926 @@ +{ + "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 \",\"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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 ", + "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" + } + } + } +} \ No newline at end of file diff --git a/deployments/fuji/solcInputs/893c7c8579088197a1acbd2718e7b759.json b/deployments/fuji/solcInputs/893c7c8579088197a1acbd2718e7b759.json new file mode 100644 index 00000000..28092e6e --- /dev/null +++ b/deployments/fuji/solcInputs/893c7c8579088197a1acbd2718e7b759.json @@ -0,0 +1,97 @@ +{ + "language": "Solidity", + "sources": { + "src/bridges/facets/StargateFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.4;\r\n\r\nimport {IStargateRouter} from \"../interfaces/IStargateRouter.sol\";\r\nimport {IStargateReceiver} from \"../interfaces/IStargateReceiver.sol\";\r\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\r\nimport {ReentrancyGuard} from \"../../common/helpers/DiamondReentrancyGuard.sol\";\r\nimport {CannotBridgeToSameNetwork, InvalidAmount, InvalidConfig} from \"../errors/GenericErrors.sol\";\r\nimport {SenderNotStargateRouter, NoMsgValueForCrossChainMessage, StargateRouterAddressZero, InvalidSourcePoolId, InvalidDestinationPoolId} from \"../errors/StargateErrors.sol\";\r\nimport {LibDiamond} from \"../libs/LibDiamond.sol\";\r\n\r\n/// @title StargateFacet\r\n/// @author Luke Wickens \r\n/// @notice Stargate/LayerZero intergration for bridging tokens\r\n\r\ncontract StargateFacet is IStargateReceiver, ReentrancyGuard {\r\n using SafeERC20 for IERC20;\r\n\r\n //////////////////////////////////////////////////////////////\r\n /////////////////////////// Events ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n event SGInitialized(address stargate, uint16 chainId);\r\n event SGTransferStarted(\r\n string bridgeUsed,\r\n address fromToken,\r\n address toToken,\r\n address from,\r\n address to,\r\n uint256 amount,\r\n uint16 chainIdTo\r\n );\r\n event SGReceivedOnDestination(address token, uint256 amount);\r\n event SGUpdatedRouter(address newAddress);\r\n event SGUpdatedSlippageTolerance(uint256 newSlippage);\r\n event SGAddedPool(uint16 chainId, address token, uint16 poolId);\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////////// Storage ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n bytes32 internal constant NAMESPACE =\r\n keccak256(\"io.etherspot.facets.stargate\");\r\n struct Storage {\r\n address stargateRouter;\r\n uint16 chainId;\r\n uint256 dstGas;\r\n uint256 slippage;\r\n mapping(uint16 => mapping(address => uint16)) poolIds;\r\n }\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////////// Structs ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n struct StargateData {\r\n uint256 qty;\r\n address fromToken;\r\n address toToken;\r\n uint16 dstChainId;\r\n address to;\r\n address destStargateComposed;\r\n }\r\n\r\n /// @notice initializes state variables for the Stargate facet\r\n /// @param _stargateRouter - address of the Stargate router contract\r\n /// @param _chainId - current chain id\r\n function sgInitialize(address _stargateRouter, uint16 _chainId) external {\r\n if (_stargateRouter == address(0)) revert InvalidConfig();\r\n LibDiamond.enforceIsContractOwner();\r\n Storage storage s = getStorage();\r\n s.stargateRouter = address(_stargateRouter);\r\n s.chainId = _chainId;\r\n s.slippage = 50; // equates to 0.5%\r\n // Adding pre-existing pools => USDC: 1, USDT: 2, BUSD: 5\r\n sgAddPool(1, 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, 1);\r\n sgAddPool(1, 0xdAC17F958D2ee523a2206206994597C13D831ec7, 2);\r\n sgAddPool(2, 0x55d398326f99059fF775485246999027B3197955, 2);\r\n sgAddPool(2, 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56, 5);\r\n sgAddPool(6, 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E, 1);\r\n sgAddPool(6, 0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7, 2);\r\n sgAddPool(9, 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174, 1);\r\n sgAddPool(9, 0xc2132D05D31c914a87C6611C10748AEb04B58e8F, 2);\r\n sgAddPool(10, 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8, 1);\r\n sgAddPool(10, 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9, 2);\r\n sgAddPool(11, 0x7F5c764cBc14f9669B88837ca1490cCa17c31607, 1);\r\n sgAddPool(12, 0x04068DA6C83AFCFA0e13ba15A6696662335D5B75, 1);\r\n emit SGInitialized(_stargateRouter, _chainId);\r\n }\r\n\r\n /// @notice initializes state variables for the stargate facet\r\n /// @param _sgData - struct containing information required to execute bridge\r\n function sgBridgeTokens(StargateData memory _sgData)\r\n external\r\n payable\r\n nonReentrant\r\n {\r\n // if (msg.value <= 0) revert NoMsgValueForCrossChainMessage();\r\n if (_sgData.qty <= 0) revert InvalidAmount();\r\n if (\r\n _sgData.fromToken == address(0) ||\r\n _sgData.toToken == address(0) ||\r\n _sgData.to == address(0) ||\r\n _sgData.destStargateComposed == address(0)\r\n ) revert InvalidConfig();\r\n\r\n // access storage\r\n Storage storage s = getStorage();\r\n\r\n // check pool ids are valid\r\n uint16 srcPoolId = sgRetrievePoolId(s.chainId, _sgData.fromToken);\r\n if (srcPoolId == 0) revert InvalidSourcePoolId();\r\n uint16 dstPoolId = sgRetrievePoolId(\r\n _sgData.dstChainId,\r\n _sgData.toToken\r\n );\r\n\r\n // calculate cross chain fees\r\n uint256 fees = sgCalculateFees(\r\n _sgData.dstChainId,\r\n _sgData.to,\r\n s.stargateRouter\r\n );\r\n\r\n // calculate slippage\r\n uint256 minAmountOut = sgMinAmountOut(_sgData.qty);\r\n\r\n // encode sgReceive implemented\r\n bytes memory destination = abi.encodePacked(\r\n _sgData.destStargateComposed\r\n );\r\n\r\n // encode payload data to send to destination contract, which it will handle with sgReceive()\r\n bytes memory payload = abi.encode(_sgData.to);\r\n\r\n // this contract calls stargate swap()\r\n IERC20(_sgData.fromToken).safeTransferFrom(\r\n msg.sender,\r\n address(this),\r\n _sgData.qty\r\n );\r\n\r\n IERC20(_sgData.fromToken).safeApprove(\r\n address(s.stargateRouter),\r\n _sgData.qty\r\n );\r\n\r\n // Stargate's Router.swap() function sends the tokens to the destination chain.\r\n IStargateRouter(s.stargateRouter).swap{value: fees}(\r\n _sgData.dstChainId, // the destination chain id\r\n srcPoolId, // the source Stargate poolId\r\n dstPoolId, // the destination Stargate poolId\r\n payable(msg.sender), // refund adddress. if msg.sender pays too much gas, return extra eth\r\n _sgData.qty, // total tokens to send to destination chain\r\n minAmountOut, // min amount allowed out\r\n IStargateRouter.lzTxObj(200000, 0, \"0x\"), // default lzTxObj\r\n destination, // destination address, the sgReceive() implementer\r\n payload // bytes payload\r\n );\r\n\r\n emit SGTransferStarted(\r\n \"stargate\",\r\n _sgData.fromToken,\r\n _sgData.toToken,\r\n msg.sender,\r\n _sgData.to,\r\n _sgData.qty,\r\n _sgData.dstChainId\r\n );\r\n }\r\n\r\n /// @notice required to receive tokens on destination chain\r\n /// @param _chainId The remote chainId sending the tokens\r\n /// @param _srcAddress The remote Bridge address\r\n /// @param _nonce The message ordering nonce\r\n /// @param _token The token contract on the local chain\r\n /// @param amountLD The qty of local _token contract tokens\r\n /// @param _payload The bytes containing the toAddress\r\n function sgReceive(\r\n uint16 _chainId,\r\n bytes memory _srcAddress,\r\n uint256 _nonce,\r\n address _token,\r\n uint256 amountLD,\r\n bytes memory _payload\r\n ) external override {\r\n Storage storage s = getStorage();\r\n if (msg.sender != address(s.stargateRouter))\r\n revert SenderNotStargateRouter();\r\n\r\n address _toAddr = abi.decode(_payload, (address));\r\n IERC20(_token).transfer(_toAddr, amountLD);\r\n emit SGReceivedOnDestination(_token, amountLD);\r\n }\r\n\r\n /// @notice Calculates cross chain fee\r\n /// @param _destChain Destination chain id\r\n /// @param _receiver Receiver on destination chain\r\n /// @param _router Address of stargate router\r\n function sgCalculateFees(\r\n uint16 _destChain,\r\n address _receiver,\r\n address _router\r\n ) public view returns (uint256) {\r\n (uint256 nativeFee, ) = IStargateRouter(_router).quoteLayerZeroFee(\r\n _destChain, // destination chain id\r\n 1, // 1 = swap\r\n abi.encodePacked(_receiver), // receiver on destination chain\r\n \"0x\", // payload, using abi.encode()\r\n IStargateRouter.lzTxObj(200000, 0, \"0x\")\r\n );\r\n return nativeFee;\r\n }\r\n\r\n /// @notice Calculates the minimum amount out using slippage tolerance\r\n /// @param _amount Transfer amount\r\n function sgMinAmountOut(uint256 _amount) public view returns (uint256) {\r\n Storage storage s = getStorage();\r\n // equates to 0.5% slippage\r\n return (_amount * (10000 - s.slippage)) / (10000);\r\n }\r\n\r\n /// @notice Updates stargate router address for deployed chain\r\n /// @param _newAddress Address of the new router\r\n function sgUpdateRouter(address _newAddress) external {\r\n LibDiamond.enforceIsContractOwner();\r\n if (_newAddress == address(0)) revert StargateRouterAddressZero();\r\n Storage storage s = getStorage();\r\n s.stargateRouter = address(_newAddress);\r\n emit SGUpdatedRouter(_newAddress);\r\n }\r\n\r\n /// @notice Updates slippage tolerance amount\r\n /// @param _newSlippage New slippage amount\r\n function sgUpdateSlippageTolerance(uint256 _newSlippage) external {\r\n LibDiamond.enforceIsContractOwner();\r\n Storage storage s = getStorage();\r\n s.slippage = _newSlippage;\r\n emit SGUpdatedSlippageTolerance(_newSlippage);\r\n }\r\n\r\n /// @notice Adds a new pool for a specific token and chain\r\n /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\r\n /// @param _token Address of token\r\n /// @param _poolId Pool id (check stargate pool ids docs)\r\n function sgAddPool(\r\n uint16 _chainId,\r\n address _token,\r\n uint16 _poolId\r\n ) public {\r\n LibDiamond.enforceIsContractOwner();\r\n Storage storage s = getStorage();\r\n s.poolIds[_chainId][_token] = _poolId;\r\n emit SGAddedPool(_chainId, _token, _poolId);\r\n }\r\n\r\n /// @notice Checks for a valid token pool on specific chain\r\n /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\r\n /// @param _token Address of token\r\n /// @param _poolId Pool id (check stargate pool ids docs)\r\n function sgCheckPoolId(\r\n uint16 _chainId,\r\n address _token,\r\n uint16 _poolId\r\n ) external view returns (bool) {\r\n Storage storage s = getStorage();\r\n return s.poolIds[_chainId][_token] == _poolId ? true : false;\r\n }\r\n\r\n /// @notice Retrieves pool id for a token on a specified chain\r\n /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\r\n /// @param _token Address of token\r\n function sgRetrievePoolId(uint16 _chainId, address _token)\r\n public\r\n view\r\n returns (uint16)\r\n {\r\n Storage storage s = getStorage();\r\n return s.poolIds[_chainId][_token];\r\n }\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////// Private Functions /////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n /// @dev fetch local storage\r\n function getStorage() private pure returns (Storage storage s) {\r\n bytes32 namespace = NAMESPACE;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n s.slot := namespace\r\n }\r\n }\r\n}\r\n" + }, + "src/bridges/interfaces/IStargateRouter.sol": { + "content": "// SPDX-License-Identifier:MIT\r\n\r\npragma solidity 0.8.4;\r\npragma abicoder v2;\r\n\r\ninterface IStargateRouter {\r\n struct lzTxObj {\r\n uint256 dstGasForCall;\r\n uint256 dstNativeAmount;\r\n bytes dstNativeAddr;\r\n }\r\n\r\n function addLiquidity(\r\n uint256 _poolId,\r\n uint256 _amountLD,\r\n address _to\r\n ) external;\r\n\r\n function swap(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLD,\r\n uint256 _minAmountLD,\r\n lzTxObj memory _lzTxParams,\r\n bytes calldata _to,\r\n bytes calldata _payload\r\n ) external payable;\r\n\r\n function redeemRemote(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLP,\r\n uint256 _minAmountLD,\r\n bytes calldata _to,\r\n lzTxObj memory _lzTxParams\r\n ) external payable;\r\n\r\n function instantRedeemLocal(\r\n uint16 _srcPoolId,\r\n uint256 _amountLP,\r\n address _to\r\n ) external returns (uint256);\r\n\r\n function redeemLocal(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress,\r\n uint256 _amountLP,\r\n bytes calldata _to,\r\n lzTxObj memory _lzTxParams\r\n ) external payable;\r\n\r\n function sendCredits(\r\n uint16 _dstChainId,\r\n uint256 _srcPoolId,\r\n uint256 _dstPoolId,\r\n address payable _refundAddress\r\n ) external payable;\r\n\r\n function quoteLayerZeroFee(\r\n uint16 _dstChainId,\r\n uint8 _functionType,\r\n bytes calldata _toAddress,\r\n bytes calldata _transferAndCallPayload,\r\n lzTxObj memory _lzTxParams\r\n ) external view returns (uint256, uint256);\r\n}\r\n" + }, + "src/bridges/interfaces/IStargateReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n\r\npragma solidity 0.8.4;\r\n\r\ninterface IStargateReceiver {\r\n function sgReceive(\r\n uint16 _srcChainId, // the remote chainId sending the tokens\r\n bytes memory _srcAddress, // the remote Bridge address\r\n uint256 _nonce,\r\n address _token, // the token contract on the local chain\r\n uint256 amountLD, // the qty of local _token contract tokens\r\n bytes memory payload\r\n ) external;\r\n}\r\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "src/common/helpers/DiamondReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.4;\r\n\r\n/// @title Reentrancy Guard\r\n/// @notice Abstract contract to provide protection against reentrancy\r\nabstract contract ReentrancyGuard {\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////////// Storage ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n bytes32 private constant NAMESPACE =\r\n keccak256(\"io.etherspot.helpers.reentrancyguard\");\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////////// Structs ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n struct ReentrancyStorage {\r\n uint256 status;\r\n }\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////////// Errors ////////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n error ReentrancyError();\r\n\r\n //////////////////////////////////////////////////////////////\r\n ///////////////////////// Constants //////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n uint256 private constant _NOT_ENTERED = 0;\r\n uint256 private constant _ENTERED = 1;\r\n\r\n //////////////////////////////////////////////////////////////\r\n ///////////////////////// Modifiers ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n modifier nonReentrant() {\r\n ReentrancyStorage storage s = reentrancyStorage();\r\n if (s.status == _ENTERED) revert ReentrancyError();\r\n s.status = _ENTERED;\r\n _;\r\n s.status = _NOT_ENTERED;\r\n }\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////// Private Functions /////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n /// @dev fetch local storage\r\n function reentrancyStorage()\r\n private\r\n pure\r\n returns (ReentrancyStorage storage data)\r\n {\r\n bytes32 position = NAMESPACE;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n data.slot := position\r\n }\r\n }\r\n}\r\n" + }, + "src/bridges/errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\nerror InvalidAmount();\r\nerror TokenAddressIsZero();\r\nerror CannotBridgeToSameNetwork();\r\nerror ZeroPostSwapBalance();\r\nerror InvalidBridgeConfigLength();\r\nerror NoSwapDataProvided();\r\nerror NativeValueWithERC();\r\nerror ContractCallNotAllowed();\r\nerror NullAddrIsNotAValidSpender();\r\nerror NullAddrIsNotAnERC20Token();\r\nerror NoTransferToNullAddress();\r\nerror NativeAssetTransferFailed();\r\nerror InvalidContract();\r\nerror InvalidConfig();\r\nerror ZeroAddressProvided();\r\n" + }, + "src/bridges/errors/StargateErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\nerror SenderNotStargateRouter();\r\nerror NoMsgValueForCrossChainMessage();\r\nerror StargateRouterAddressZero();\r\nerror InvalidSourcePoolId();\r\nerror InvalidDestinationPoolId();\r\n" + }, + "src/bridges/libs/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.8.4 <0.9.0;\r\n\r\nimport {IDiamondCut} from \"../interfaces/IDiamondCut.sol\";\r\n\r\nlibrary LibDiamond {\r\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\r\n keccak256(\"diamond.standard.diamond.storage\");\r\n\r\n struct FacetAddressAndPosition {\r\n address facetAddress;\r\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\r\n }\r\n\r\n struct FacetFunctionSelectors {\r\n bytes4[] functionSelectors;\r\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\r\n }\r\n\r\n struct DiamondStorage {\r\n // maps function selector to the facet address and\r\n // the position of the selector in the facetFunctionSelectors.selectors array\r\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\r\n // maps facet addresses to function selectors\r\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\r\n // facet addresses\r\n address[] facetAddresses;\r\n // Used to query if a contract implements an interface.\r\n // Used to implement ERC-165.\r\n mapping(bytes4 => bool) supportedInterfaces;\r\n // owner of the contract\r\n address contractOwner;\r\n }\r\n\r\n function diamondStorage()\r\n internal\r\n pure\r\n returns (DiamondStorage storage ds)\r\n {\r\n bytes32 position = DIAMOND_STORAGE_POSITION;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n ds.slot := position\r\n }\r\n }\r\n\r\n event OwnershipTransferred(\r\n address indexed previousOwner,\r\n address indexed newOwner\r\n );\r\n\r\n function setContractOwner(address _newOwner) internal {\r\n DiamondStorage storage ds = diamondStorage();\r\n address previousOwner = ds.contractOwner;\r\n ds.contractOwner = _newOwner;\r\n emit OwnershipTransferred(previousOwner, _newOwner);\r\n }\r\n\r\n function contractOwner() internal view returns (address contractOwner_) {\r\n contractOwner_ = diamondStorage().contractOwner;\r\n }\r\n\r\n function enforceIsContractOwner() internal view {\r\n require(\r\n msg.sender == diamondStorage().contractOwner,\r\n \"LibDiamond: Must be contract owner\"\r\n );\r\n }\r\n\r\n event DiamondCut(\r\n IDiamondCut.FacetCut[] _diamondCut,\r\n address _init,\r\n bytes _calldata\r\n );\r\n\r\n // Internal function version of diamondCut\r\n function diamondCut(\r\n IDiamondCut.FacetCut[] memory _diamondCut,\r\n address _init,\r\n bytes memory _calldata\r\n ) internal {\r\n for (\r\n uint256 facetIndex;\r\n facetIndex < _diamondCut.length;\r\n facetIndex++\r\n ) {\r\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\r\n if (action == IDiamondCut.FacetCutAction.Add) {\r\n addFunctions(\r\n _diamondCut[facetIndex].facetAddress,\r\n _diamondCut[facetIndex].functionSelectors\r\n );\r\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\r\n replaceFunctions(\r\n _diamondCut[facetIndex].facetAddress,\r\n _diamondCut[facetIndex].functionSelectors\r\n );\r\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\r\n removeFunctions(\r\n _diamondCut[facetIndex].facetAddress,\r\n _diamondCut[facetIndex].functionSelectors\r\n );\r\n } else {\r\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\r\n }\r\n }\r\n emit DiamondCut(_diamondCut, _init, _calldata);\r\n initializeDiamondCut(_init, _calldata);\r\n }\r\n\r\n function addFunctions(\r\n address _facetAddress,\r\n bytes4[] memory _functionSelectors\r\n ) internal {\r\n require(\r\n _functionSelectors.length > 0,\r\n \"LibDiamondCut: No selectors in facet to cut\"\r\n );\r\n DiamondStorage storage ds = diamondStorage();\r\n require(\r\n _facetAddress != address(0),\r\n \"LibDiamondCut: Add facet can't be address(0)\"\r\n );\r\n uint96 selectorPosition = uint96(\r\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\r\n );\r\n // add new facet address if it does not exist\r\n if (selectorPosition == 0) {\r\n addFacet(ds, _facetAddress);\r\n }\r\n for (\r\n uint256 selectorIndex;\r\n selectorIndex < _functionSelectors.length;\r\n selectorIndex++\r\n ) {\r\n bytes4 selector = _functionSelectors[selectorIndex];\r\n address oldFacetAddress = ds\r\n .selectorToFacetAndPosition[selector]\r\n .facetAddress;\r\n require(\r\n oldFacetAddress == address(0),\r\n \"LibDiamondCut: Can't add function that already exists\"\r\n );\r\n addFunction(ds, selector, selectorPosition, _facetAddress);\r\n selectorPosition++;\r\n }\r\n }\r\n\r\n function replaceFunctions(\r\n address _facetAddress,\r\n bytes4[] memory _functionSelectors\r\n ) internal {\r\n require(\r\n _functionSelectors.length > 0,\r\n \"LibDiamondCut: No selectors in facet to cut\"\r\n );\r\n DiamondStorage storage ds = diamondStorage();\r\n require(\r\n _facetAddress != address(0),\r\n \"LibDiamondCut: Add facet can't be address(0)\"\r\n );\r\n uint96 selectorPosition = uint96(\r\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\r\n );\r\n // add new facet address if it does not exist\r\n if (selectorPosition == 0) {\r\n addFacet(ds, _facetAddress);\r\n }\r\n for (\r\n uint256 selectorIndex;\r\n selectorIndex < _functionSelectors.length;\r\n selectorIndex++\r\n ) {\r\n bytes4 selector = _functionSelectors[selectorIndex];\r\n address oldFacetAddress = ds\r\n .selectorToFacetAndPosition[selector]\r\n .facetAddress;\r\n require(\r\n oldFacetAddress != _facetAddress,\r\n \"LibDiamondCut: Can't replace function with same function\"\r\n );\r\n removeFunction(ds, oldFacetAddress, selector);\r\n addFunction(ds, selector, selectorPosition, _facetAddress);\r\n selectorPosition++;\r\n }\r\n }\r\n\r\n function removeFunctions(\r\n address _facetAddress,\r\n bytes4[] memory _functionSelectors\r\n ) internal {\r\n require(\r\n _functionSelectors.length > 0,\r\n \"LibDiamondCut: No selectors in facet to cut\"\r\n );\r\n DiamondStorage storage ds = diamondStorage();\r\n // if function does not exist then do nothing and return\r\n require(\r\n _facetAddress == address(0),\r\n \"LibDiamondCut: Remove facet address must be address(0)\"\r\n );\r\n for (\r\n uint256 selectorIndex;\r\n selectorIndex < _functionSelectors.length;\r\n selectorIndex++\r\n ) {\r\n bytes4 selector = _functionSelectors[selectorIndex];\r\n address oldFacetAddress = ds\r\n .selectorToFacetAndPosition[selector]\r\n .facetAddress;\r\n removeFunction(ds, oldFacetAddress, selector);\r\n }\r\n }\r\n\r\n function addFacet(DiamondStorage storage ds, address _facetAddress)\r\n internal\r\n {\r\n enforceHasContractCode(\r\n _facetAddress,\r\n \"LibDiamondCut: New facet has no code\"\r\n );\r\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\r\n .facetAddresses\r\n .length;\r\n ds.facetAddresses.push(_facetAddress);\r\n }\r\n\r\n function addFunction(\r\n DiamondStorage storage ds,\r\n bytes4 _selector,\r\n uint96 _selectorPosition,\r\n address _facetAddress\r\n ) internal {\r\n ds\r\n .selectorToFacetAndPosition[_selector]\r\n .functionSelectorPosition = _selectorPosition;\r\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\r\n _selector\r\n );\r\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\r\n }\r\n\r\n function removeFunction(\r\n DiamondStorage storage ds,\r\n address _facetAddress,\r\n bytes4 _selector\r\n ) internal {\r\n require(\r\n _facetAddress != address(0),\r\n \"LibDiamondCut: Can't remove function that doesn't exist\"\r\n );\r\n // an immutable function is a function defined directly in a diamond\r\n require(\r\n _facetAddress != address(this),\r\n \"LibDiamondCut: Can't remove immutable function\"\r\n );\r\n // replace selector with last selector, then delete last selector\r\n uint256 selectorPosition = ds\r\n .selectorToFacetAndPosition[_selector]\r\n .functionSelectorPosition;\r\n uint256 lastSelectorPosition = ds\r\n .facetFunctionSelectors[_facetAddress]\r\n .functionSelectors\r\n .length - 1;\r\n // if not the same then replace _selector with lastSelector\r\n if (selectorPosition != lastSelectorPosition) {\r\n bytes4 lastSelector = ds\r\n .facetFunctionSelectors[_facetAddress]\r\n .functionSelectors[lastSelectorPosition];\r\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\r\n selectorPosition\r\n ] = lastSelector;\r\n ds\r\n .selectorToFacetAndPosition[lastSelector]\r\n .functionSelectorPosition = uint96(selectorPosition);\r\n }\r\n // delete the last selector\r\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\r\n delete ds.selectorToFacetAndPosition[_selector];\r\n\r\n // if no more selectors for facet address then delete the facet address\r\n if (lastSelectorPosition == 0) {\r\n // replace facet address with last facet address and delete last facet address\r\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\r\n uint256 facetAddressPosition = ds\r\n .facetFunctionSelectors[_facetAddress]\r\n .facetAddressPosition;\r\n if (facetAddressPosition != lastFacetAddressPosition) {\r\n address lastFacetAddress = ds.facetAddresses[\r\n lastFacetAddressPosition\r\n ];\r\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\r\n ds\r\n .facetFunctionSelectors[lastFacetAddress]\r\n .facetAddressPosition = facetAddressPosition;\r\n }\r\n ds.facetAddresses.pop();\r\n delete ds\r\n .facetFunctionSelectors[_facetAddress]\r\n .facetAddressPosition;\r\n }\r\n }\r\n\r\n function initializeDiamondCut(address _init, bytes memory _calldata)\r\n internal\r\n {\r\n if (_init == address(0)) {\r\n require(\r\n _calldata.length == 0,\r\n \"LibDiamondCut: _init is address(0) but_calldata is not empty\"\r\n );\r\n } else {\r\n require(\r\n _calldata.length > 0,\r\n \"LibDiamondCut: _calldata is empty but _init is not address(0)\"\r\n );\r\n if (_init != address(this)) {\r\n enforceHasContractCode(\r\n _init,\r\n \"LibDiamondCut: _init address has no code\"\r\n );\r\n }\r\n // solhint-disable-next-line avoid-low-level-calls\r\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\r\n if (!success) {\r\n if (error.length > 0) {\r\n // bubble up the error\r\n revert(string(error));\r\n } else {\r\n revert(\"LibDiamondCut: _init function reverted\");\r\n }\r\n }\r\n }\r\n }\r\n\r\n function enforceHasContractCode(\r\n address _contract,\r\n string memory _errorMessage\r\n ) internal view {\r\n uint256 contractSize;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n contractSize := extcodesize(_contract)\r\n }\r\n require(contractSize > 0, _errorMessage);\r\n }\r\n}\r\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "src/bridges/interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.8.4 <0.9.0;\r\n\r\ninterface IDiamondCut {\r\n enum FacetCutAction {\r\n Add,\r\n Replace,\r\n Remove\r\n }\r\n // Add=0, Replace=1, Remove=2\r\n\r\n struct FacetCut {\r\n address facetAddress;\r\n FacetCutAction action;\r\n bytes4[] functionSelectors;\r\n }\r\n\r\n /// @notice Add/replace/remove any number of functions and optionally execute\r\n /// a function with delegatecall\r\n /// @param _diamondCut Contains the facet addresses and function selectors\r\n /// @param _init The address of the contract or facet to execute _calldata\r\n /// @param _calldata A function call, including function selector and arguments\r\n /// _calldata is executed with delegatecall on _init\r\n function diamondCut(\r\n FacetCut[] calldata _diamondCut,\r\n address _init,\r\n bytes calldata _calldata\r\n ) external;\r\n\r\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\r\n}\r\n" + }, + "src/bridges/libs/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\nimport {NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeValueWithERC, NativeAssetTransferFailed} from \"../errors/GenericErrors.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\n\r\n/// @title LibAsset\r\n/// @author Connext \r\n/// @notice This library contains helpers for dealing with onchain transfers\r\n/// of assets, including accounting for the native asset `assetId`\r\n/// conventions and any noncompliant ERC20 transfers\r\nlibrary LibAsset {\r\n uint256 private constant MAX_INT = type(uint256).max;\r\n\r\n address internal constant NULL_ADDRESS =\r\n 0x0000000000000000000000000000000000000000; //address(0)\r\n\r\n /// @dev All native assets use the empty address for their asset id\r\n /// by convention\r\n\r\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\r\n\r\n /// @notice Gets the balance of the inheriting contract for the given asset\r\n /// @param assetId The asset identifier to get the balance of\r\n /// @return Balance held by contracts using this library\r\n function getOwnBalance(address assetId) internal view returns (uint256) {\r\n return\r\n assetId == NATIVE_ASSETID\r\n ? address(this).balance\r\n : IERC20(assetId).balanceOf(address(this));\r\n }\r\n\r\n /// @notice Transfers ether from the inheriting contract to a given\r\n /// recipient\r\n /// @param recipient Address to send ether to\r\n /// @param amount Amount to send to given recipient\r\n function transferNativeAsset(address payable recipient, uint256 amount)\r\n private\r\n {\r\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\r\n // solhint-disable-next-line avoid-low-level-calls\r\n (bool success, ) = recipient.call{value: amount}(\"\");\r\n if (!success) revert NativeAssetTransferFailed();\r\n }\r\n\r\n /// @notice Gives MAX approval for another address to spend tokens\r\n /// @param assetId Token address to transfer\r\n /// @param spender Address to give spend approval to\r\n /// @param amount Amount to approve for spending\r\n function maxApproveERC20(\r\n IERC20 assetId,\r\n address spender,\r\n uint256 amount\r\n ) internal {\r\n if (address(assetId) == NATIVE_ASSETID) return;\r\n if (spender == NULL_ADDRESS) revert NullAddrIsNotAValidSpender();\r\n uint256 allowance = assetId.allowance(address(this), spender);\r\n if (allowance < amount)\r\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_INT);\r\n }\r\n\r\n /// @notice Transfers tokens from the inheriting contract to a given\r\n /// recipient\r\n /// @param assetId Token address to transfer\r\n /// @param recipient Address to send token to\r\n /// @param amount Amount to send to given recipient\r\n function transferERC20(\r\n address assetId,\r\n address recipient,\r\n uint256 amount\r\n ) private {\r\n if (isNativeAsset(assetId)) revert NullAddrIsNotAnERC20Token();\r\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\r\n }\r\n\r\n /// @notice Transfers tokens from a sender to a given recipient\r\n /// @param assetId Token address to transfer\r\n /// @param from Address of sender/owner\r\n /// @param to Address of recipient/spender\r\n /// @param amount Amount to transfer from owner to spender\r\n function transferFromERC20(\r\n address assetId,\r\n address from,\r\n address to,\r\n uint256 amount\r\n ) internal {\r\n if (assetId == NATIVE_ASSETID) revert NullAddrIsNotAnERC20Token();\r\n if (to == NULL_ADDRESS) revert NoTransferToNullAddress();\r\n SafeERC20.safeTransferFrom(IERC20(assetId), from, to, amount);\r\n }\r\n\r\n /// @notice Deposits an asset into the contract and performs checks to avoid NativeValueWithERC\r\n /// @param tokenId Token to deposit\r\n /// @param amount Amount to deposit\r\n /// @param isNative Wether the token is native or ERC20\r\n function depositAsset(\r\n address tokenId,\r\n uint256 amount,\r\n bool isNative\r\n ) internal {\r\n if (amount == 0) revert InvalidAmount();\r\n if (isNative) {\r\n if (msg.value != amount) revert InvalidAmount();\r\n } else {\r\n if (msg.value != 0) revert NativeValueWithERC();\r\n uint256 _fromTokenBalance = LibAsset.getOwnBalance(tokenId);\r\n LibAsset.transferFromERC20(\r\n tokenId,\r\n msg.sender,\r\n address(this),\r\n amount\r\n );\r\n if (LibAsset.getOwnBalance(tokenId) - _fromTokenBalance != amount)\r\n revert InvalidAmount();\r\n }\r\n }\r\n\r\n /// @notice Overload for depositAsset(address tokenId, uint256 amount, bool isNative)\r\n /// @param tokenId Token to deposit\r\n /// @param amount Amount to deposit\r\n function depositAsset(address tokenId, uint256 amount) internal {\r\n return depositAsset(tokenId, amount, tokenId == NATIVE_ASSETID);\r\n }\r\n\r\n /// @notice Determines whether the given assetId is the native asset\r\n /// @param assetId The asset identifier to evaluate\r\n /// @return Boolean indicating if the asset is the native asset\r\n function isNativeAsset(address assetId) internal pure returns (bool) {\r\n return assetId == NATIVE_ASSETID;\r\n }\r\n\r\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\r\n /// some recipient. Should handle all non-compliant return value\r\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\r\n /// @param assetId Asset id for transfer (address(0) for native asset,\r\n /// token address for erc20s)\r\n /// @param recipient Address to send asset to\r\n /// @param amount Amount to send to given recipient\r\n function transferAsset(\r\n address assetId,\r\n address payable recipient,\r\n uint256 amount\r\n ) internal {\r\n (assetId == NATIVE_ASSETID)\r\n ? transferNativeAsset(recipient, amount)\r\n : transferERC20(assetId, recipient, amount);\r\n }\r\n\r\n /// @dev Checks whether the given address is a contract and contains code\r\n function isContract(address _contractAddr) internal view returns (bool) {\r\n uint256 size;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n size := extcodesize(_contractAddr)\r\n }\r\n return size > 0;\r\n }\r\n}\r\n" + }, + "src/common/helpers/BalancesHelperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\n/// @title BalancesHelperV2\r\n/// @author Luke Wickens \r\n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\r\n\r\nimport {ISuperfluidToken} from \"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\";\r\nimport {IERC20} from \"@openzeppelin/contracts/interfaces/IERC20.sol\";\r\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\r\n\r\ncontract BalancesHelperV2 {\r\n using Address for address;\r\n\r\n /// @notice Custom errors to handle address(0)\r\n error AccountZeroAddress(address account, address token);\r\n error TokenZeroAddress(address account, address token);\r\n\r\n constructor() {}\r\n\r\n /// @notice Returns balances of accounts for multiple ERC20 tokens.\r\n /// @dev Error thrown if: account or token address is address(0),\r\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\r\n /// @param accounts = Array of accounts addresses\r\n /// @param tokens = Array of tokens addresses\r\n /// @return One-dimensional that's accounts.length * tokens.length long. The\r\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\r\n\r\n function getBalances(address[] calldata accounts, address[] calldata tokens)\r\n external\r\n view\r\n returns (uint256[] memory)\r\n {\r\n uint256[] memory result = new uint256[](\r\n accounts.length * tokens.length\r\n );\r\n\r\n for (uint256 i; i < accounts.length; i++) {\r\n for (uint256 j; j < tokens.length; j++) {\r\n uint256 index = j + (tokens.length * i);\r\n result[index] = _getBalance(accounts[i], tokens[j]);\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\r\n /// @dev Error thrown if: account or token address is address(0),\r\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\r\n /// @param accounts = Array of accounts addresses\r\n /// @param tokens = Array of tokens addresses\r\n /// @return One-dimensional that's accounts.length * tokens.length long. The\r\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\r\n\r\n function getSuperfluidWrappedTokenBalances(\r\n address[] calldata accounts,\r\n address[] calldata tokens\r\n ) external view returns (int256[] memory) {\r\n int256[] memory result = new int256[](accounts.length * tokens.length);\r\n\r\n for (uint256 i; i < accounts.length; i++) {\r\n for (uint256 j; j < tokens.length; j++) {\r\n uint256 index = j + (tokens.length * i);\r\n result[index] = _getSuperfluidWrappedTokenBalance(\r\n accounts[i],\r\n tokens[j]\r\n );\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n /// Private fuctions\r\n\r\n /// @notice Returns balance of account for an ERC20 token.\r\n /// @dev Error thrown if: account or token address is address(0)\r\n /// @param account = account address\r\n /// @param token = tokens address\r\n /// @return balance of account as uint256.\r\n\r\n function _getBalance(address account, address token)\r\n private\r\n view\r\n returns (uint256)\r\n {\r\n if (account == address(0)) revert AccountZeroAddress(account, token);\r\n if (token == address(0)) revert TokenZeroAddress(account, token);\r\n\r\n bytes memory returnedData = token.functionStaticCall(\r\n abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\r\n );\r\n\r\n return abi.decode(returnedData, (uint256));\r\n }\r\n\r\n /// @notice Returns real balance of a user, taking into consideration all agreements of account\r\n /// @dev Error thrown if: account or token address is address(0)\r\n /// @param account = account address\r\n /// @param token = tokens address\r\n /// @return available balance of account as int256.\r\n\r\n function _getSuperfluidWrappedTokenBalance(address account, address token)\r\n private\r\n view\r\n returns (int256)\r\n {\r\n if (account == address(0)) revert AccountZeroAddress(account, token);\r\n if (token == address(0)) revert TokenZeroAddress(account, token);\r\n\r\n bytes memory returnedData = token.functionStaticCall(\r\n abi.encodeWithSelector(\r\n ISuperfluidToken(token).realtimeBalanceOfNow.selector,\r\n account\r\n )\r\n );\r\n\r\n (int256 availableBalance, , , ) = abi.decode(\r\n returnedData,\r\n (int256, uint256, uint256, uint256)\r\n );\r\n return availableBalance;\r\n }\r\n}\r\n" + }, + "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol": { + "content": "// SPDX-License-Identifier: AGPLv3\npragma solidity >= 0.8.0;\n\nimport { ISuperAgreement } from \"./ISuperAgreement.sol\";\n\n\n/**\n * @title Superfluid token interface\n * @author Superfluid\n */\ninterface ISuperfluidToken {\n\n /**************************************************************************\n * Basic information\n *************************************************************************/\n\n /**\n * @dev Get superfluid host contract address\n */\n function getHost() external view returns(address host);\n\n /**\n * @dev Encoded liquidation type data mainly used for handling stack to deep errors\n *\n * Note:\n * - version: 1\n * - liquidationType key:\n * - 0 = reward account receives reward (PIC period)\n * - 1 = liquidator account receives reward (Pleb period)\n * - 2 = liquidator account receives reward (Pirate period/bailout)\n */\n struct LiquidationTypeData {\n uint256 version;\n uint8 liquidationType;\n }\n\n /**************************************************************************\n * Real-time balance functions\n *************************************************************************/\n\n /**\n * @dev Calculate the real balance of a user, taking in consideration all agreements of the account\n * @param account for the query\n * @param timestamp Time of balance\n * @return availableBalance Real-time balance\n * @return deposit Account deposit\n * @return owedDeposit Account owed Deposit\n */\n function realtimeBalanceOf(\n address account,\n uint256 timestamp\n )\n external view\n returns (\n int256 availableBalance,\n uint256 deposit,\n uint256 owedDeposit);\n\n /**\n * @notice Calculate the realtime balance given the current host.getNow() value\n * @dev realtimeBalanceOf with timestamp equals to block timestamp\n * @param account for the query\n * @return availableBalance Real-time balance\n * @return deposit Account deposit\n * @return owedDeposit Account owed Deposit\n */\n function realtimeBalanceOfNow(\n address account\n )\n external view\n returns (\n int256 availableBalance,\n uint256 deposit,\n uint256 owedDeposit,\n uint256 timestamp);\n\n /**\n * @notice Check if account is critical\n * @dev A critical account is when availableBalance < 0\n * @param account The account to check\n * @param timestamp The time we'd like to check if the account is critical (should use future)\n * @return isCritical Whether the account is critical\n */\n function isAccountCritical(\n address account,\n uint256 timestamp\n )\n external view\n returns(bool isCritical);\n\n /**\n * @notice Check if account is critical now (current host.getNow())\n * @dev A critical account is when availableBalance < 0\n * @param account The account to check\n * @return isCritical Whether the account is critical\n */\n function isAccountCriticalNow(\n address account\n )\n external view\n returns(bool isCritical);\n\n /**\n * @notice Check if account is solvent\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\n * @param account The account to check\n * @param timestamp The time we'd like to check if the account is solvent (should use future)\n * @return isSolvent\n */\n function isAccountSolvent(\n address account,\n uint256 timestamp\n )\n external view\n returns(bool isSolvent);\n\n /**\n * @notice Check if account is solvent now\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\n * @param account The account to check\n * @return isSolvent\n */\n function isAccountSolventNow(\n address account\n )\n external view\n returns(bool isSolvent);\n\n /**\n * @notice Get a list of agreements that is active for the account\n * @dev An active agreement is one that has state for the account\n * @param account Account to query\n * @return activeAgreements List of accounts that have non-zero states for the account\n */\n function getAccountActiveAgreements(address account)\n external view\n returns(ISuperAgreement[] memory activeAgreements);\n\n\n /**************************************************************************\n * Super Agreement hosting functions\n *************************************************************************/\n\n /**\n * @dev Create a new agreement\n * @param id Agreement ID\n * @param data Agreement data\n */\n function createAgreement(\n bytes32 id,\n bytes32[] calldata data\n )\n external;\n /**\n * @dev Agreement created event\n * @param agreementClass Contract address of the agreement\n * @param id Agreement ID\n * @param data Agreement data\n */\n event AgreementCreated(\n address indexed agreementClass,\n bytes32 id,\n bytes32[] data\n );\n\n /**\n * @dev Get data of the agreement\n * @param agreementClass Contract address of the agreement\n * @param id Agreement ID\n * @return data Data of the agreement\n */\n function getAgreementData(\n address agreementClass,\n bytes32 id,\n uint dataLength\n )\n external view\n returns(bytes32[] memory data);\n\n /**\n * @dev Create a new agreement\n * @param id Agreement ID\n * @param data Agreement data\n */\n function updateAgreementData(\n bytes32 id,\n bytes32[] calldata data\n )\n external;\n /**\n * @dev Agreement updated event\n * @param agreementClass Contract address of the agreement\n * @param id Agreement ID\n * @param data Agreement data\n */\n event AgreementUpdated(\n address indexed agreementClass,\n bytes32 id,\n bytes32[] data\n );\n\n /**\n * @dev Close the agreement\n * @param id Agreement ID\n */\n function terminateAgreement(\n bytes32 id,\n uint dataLength\n )\n external;\n /**\n * @dev Agreement terminated event\n * @param agreementClass Contract address of the agreement\n * @param id Agreement ID\n */\n event AgreementTerminated(\n address indexed agreementClass,\n bytes32 id\n );\n\n /**\n * @dev Update agreement state slot\n * @param account Account to be updated\n *\n * NOTE\n * - To clear the storage out, provide zero-ed array of intended length\n */\n function updateAgreementStateSlot(\n address account,\n uint256 slotId,\n bytes32[] calldata slotData\n )\n external;\n /**\n * @dev Agreement account state updated event\n * @param agreementClass Contract address of the agreement\n * @param account Account updated\n * @param slotId slot id of the agreement state\n */\n event AgreementStateUpdated(\n address indexed agreementClass,\n address indexed account,\n uint256 slotId\n );\n\n /**\n * @dev Get data of the slot of the state of an agreement\n * @param agreementClass Contract address of the agreement\n * @param account Account to query\n * @param slotId slot id of the state\n * @param dataLength length of the state data\n */\n function getAgreementStateSlot(\n address agreementClass,\n address account,\n uint256 slotId,\n uint dataLength\n )\n external view\n returns (bytes32[] memory slotData);\n\n /**\n * @notice Settle balance from an account by the agreement\n * @dev The agreement needs to make sure that the balance delta is balanced afterwards\n * @param account Account to query.\n * @param delta Amount of balance delta to be settled\n *\n * Modifiers:\n * - onlyAgreement\n */\n function settleBalance(\n address account,\n int256 delta\n )\n external;\n\n /**\n * @dev Make liquidation payouts (v2)\n * @param id Agreement ID\n * @param liquidationTypeData Data regarding the version of the liquidation schema and the type\n * @param liquidatorAccount Address of the executor of the liquidation\n * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount\n * @param targetAccount Account of the stream sender\n * @param rewardAmount The amount the reward recepient account will receive\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\n *\n * - If a bailout is required (bailoutAmount > 0)\n * - the actual reward (single deposit) goes to the executor,\n * - while the reward account becomes the bailout account\n * - total bailout include: bailout amount + reward amount\n * - the targetAccount will be bailed out\n * - If a bailout is not required\n * - the targetAccount will pay the rewardAmount\n * - the liquidator (reward account in PIC period) will receive the rewardAmount\n *\n * Modifiers:\n * - onlyAgreement\n */\n function makeLiquidationPayoutsV2\n (\n bytes32 id,\n bytes memory liquidationTypeData,\n address liquidatorAccount,\n bool useDefaultRewardAccount,\n address targetAccount,\n uint256 rewardAmount,\n int256 targetAccountBalanceDelta\n ) external;\n /**\n * @dev Agreement liquidation event v2 (including agent account)\n * @param agreementClass Contract address of the agreement\n * @param id Agreement ID\n * @param liquidatorAccount Address of the executor of the liquidation\n * @param targetAccount Account of the stream sender\n * @param rewardAccount Account that collects the reward or bails out insolvent accounts\n * @param rewardAmount The amount the reward recipient account balance should change by\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\n * @param liquidationTypeData The encoded liquidation type data including the version (how to decode)\n *\n * NOTE:\n * Reward account rule:\n * - if the agreement is liquidated during the PIC period\n * - the rewardAccount will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount\n * - the targetAccount will pay for the rewardAmount\n * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent\n * - the liquidatorAccount will get the rewardAmount (remaining deposit)\n * - the targetAccount will pay for the rewardAmount\n * - if the targetAccount is insolvent\n * - the liquidatorAccount will get the rewardAmount (single deposit)\n * - the rewardAccount will pay for both the rewardAmount and bailoutAmount\n * - the targetAccount will receive the bailoutAmount\n */\n event AgreementLiquidatedV2(\n address indexed agreementClass,\n bytes32 id,\n address indexed liquidatorAccount,\n address indexed targetAccount,\n address rewardAccount,\n uint256 rewardAmount,\n int256 targetAccountBalanceDelta,\n bytes liquidationTypeData\n );\n\n /**************************************************************************\n * Function modifiers for access control and parameter validations\n *\n * While they cannot be explicitly stated in function definitions, they are\n * listed in function definition comments instead for clarity.\n *\n * NOTE: solidity-coverage not supporting it\n *************************************************************************/\n\n /// @dev The msg.sender must be host contract\n //modifier onlyHost() virtual;\n\n /// @dev The msg.sender must be a listed agreement.\n //modifier onlyAgreement() virtual;\n\n /**************************************************************************\n * DEPRECATED\n *************************************************************************/\n\n /**\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy)\n * @param agreementClass Contract address of the agreement\n * @param id Agreement ID\n * @param penaltyAccount Account of the agreement to be penalized\n * @param rewardAccount Account that collect the reward\n * @param rewardAmount Amount of liquidation reward\n *\n * NOTE:\n *\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\n */\n event AgreementLiquidated(\n address indexed agreementClass,\n bytes32 id,\n address indexed penaltyAccount,\n address indexed rewardAccount,\n uint256 rewardAmount\n );\n\n /**\n * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy)\n * @param bailoutAccount Account that bailout the penalty account\n * @param bailoutAmount Amount of account bailout\n *\n * NOTE:\n *\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\n */\n event Bailout(\n address indexed bailoutAccount,\n uint256 bailoutAmount\n );\n\n /**\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2)\n * @param liquidatorAccount Account of the agent that performed the liquidation.\n * @param agreementClass Contract address of the agreement\n * @param id Agreement ID\n * @param penaltyAccount Account of the agreement to be penalized\n * @param bondAccount Account that collect the reward or bailout accounts\n * @param rewardAmount Amount of liquidation reward\n * @param bailoutAmount Amount of liquidation bailouot\n *\n * NOTE:\n * Reward account rule:\n * - if bailout is equal to 0, then\n * - the bondAccount will get the rewardAmount,\n * - the penaltyAccount will pay for the rewardAmount.\n * - if bailout is larger than 0, then\n * - the liquidatorAccount will get the rewardAmouont,\n * - the bondAccount will pay for both the rewardAmount and bailoutAmount,\n * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.\n */\n event AgreementLiquidatedBy(\n address liquidatorAccount,\n address indexed agreementClass,\n bytes32 id,\n address indexed penaltyAccount,\n address indexed bondAccount,\n uint256 rewardAmount,\n uint256 bailoutAmount\n );\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\n" + }, + "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperAgreement.sol": { + "content": "// SPDX-License-Identifier: AGPLv3\npragma solidity >= 0.8.0;\n\nimport { ISuperfluidToken } from \"./ISuperfluidToken.sol\";\n\n/**\n * @title Super agreement interface\n * @author Superfluid\n */\ninterface ISuperAgreement {\n\n /**\n * @dev Get the type of the agreement class\n */\n function agreementType() external view returns (bytes32);\n\n /**\n * @dev Calculate the real-time balance for the account of this agreement class\n * @param account Account the state belongs to\n * @param time Time used for the calculation\n * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement\n * @return deposit Account deposit amount of this agreement\n * @return owedDeposit Account owed deposit amount of this agreement\n */\n function realtimeBalanceOf(\n ISuperfluidToken token,\n address account,\n uint256 time\n )\n external\n view\n returns (\n int256 dynamicBalance,\n uint256 deposit,\n uint256 owedDeposit\n );\n\n}\n" + }, + "src/bridges/facets/CBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\n/// @title CBridgeFacet\r\n/// @author Luke Wickens \r\n/// @notice cBridge intergration for bridging tokens\r\n\r\nimport {ICBridge} from \"../interfaces/ICBridge.sol\";\r\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\r\nimport {ReentrancyGuard} from \"../../common/helpers/DiamondReentrancyGuard.sol\";\r\nimport {CannotBridgeToSameNetwork, InvalidAmount, InvalidConfig, TokenAddressIsZero, ZeroAddressProvided} from \"../errors/GenericErrors.sol\";\r\nimport {CBSlippageTooLow} from \"../errors/CBridgeErrors.sol\";\r\nimport {LibDiamond} from \"../libs/LibDiamond.sol\";\r\n\r\ncontract CBridgeFacet is ReentrancyGuard {\r\n using SafeERC20 for IERC20;\r\n //////////////////////////////////////////////////////////////\r\n /////////////////////////// Events ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n event CBInitialized(address cBridge, uint256 chainId);\r\n event CBTransferStarted(\r\n string bridgeUsed,\r\n address token,\r\n address from,\r\n address to,\r\n uint256 qty,\r\n uint256 chainIdTo\r\n );\r\n event CBUpdatedBridge(address newAddress);\r\n event CBUpdatedSlippageTolerance(uint256 newSlippage);\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////////// Storage ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n bytes32 internal constant NAMESPACE =\r\n keccak256(\"io.etherspot.facets.cbridge\");\r\n struct Storage {\r\n address cbBridge;\r\n uint256 cbChainId;\r\n uint32 cbSlippage;\r\n }\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////////// Structs ///////////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n struct CBridgeData {\r\n uint64 dstChainId;\r\n uint64 nonce;\r\n uint256 qty;\r\n address to;\r\n address token;\r\n }\r\n\r\n /// @notice initializes state variables for the cBridge facet\r\n /// @param _cbBridge address of the CBridge router contract\r\n function cbInitialize(address _cbBridge) external {\r\n LibDiamond.enforceIsContractOwner();\r\n if (_cbBridge == address(0)) revert ZeroAddressProvided();\r\n Storage storage s = getStorage();\r\n s.cbBridge = _cbBridge;\r\n s.cbChainId = block.chainid;\r\n s.cbSlippage = 10000; // equates to 1% - has to be > 0.5% (slippage * 1M)\r\n emit CBInitialized(_cbBridge, block.chainid);\r\n }\r\n\r\n /// @notice initiates token bridging\r\n /// @param _cbData: provides necessary data for cBridge transfer\r\n\r\n function cbBridgeTokens(CBridgeData calldata _cbData)\r\n external\r\n payable\r\n nonReentrant\r\n {\r\n if (block.chainid == _cbData.dstChainId)\r\n revert CannotBridgeToSameNetwork();\r\n if (_cbData.to == address(0)) revert ZeroAddressProvided();\r\n if (_cbData.qty <= 0) revert InvalidAmount();\r\n if (_cbData.token == address(0)) revert TokenAddressIsZero();\r\n\r\n Storage storage s = getStorage();\r\n address bridge = s.cbBridge;\r\n\r\n // this contract calls stargate swap()\r\n IERC20(_cbData.token).safeTransferFrom(\r\n msg.sender,\r\n address(this),\r\n _cbData.qty\r\n );\r\n IERC20(_cbData.token).safeApprove(address(bridge), _cbData.qty);\r\n\r\n ICBridge(bridge).send(\r\n _cbData.to,\r\n _cbData.token,\r\n _cbData.qty,\r\n _cbData.dstChainId,\r\n _cbData.nonce,\r\n s.cbSlippage\r\n );\r\n\r\n emit CBTransferStarted(\r\n \"cbridge\",\r\n _cbData.token,\r\n msg.sender,\r\n _cbData.to,\r\n _cbData.qty,\r\n _cbData.dstChainId\r\n );\r\n }\r\n\r\n function cbUpdateSlippageTolerance(uint32 _newSlippage) external {\r\n // should be > 0.5% (5000)\r\n if (_newSlippage <= 5000) revert CBSlippageTooLow();\r\n LibDiamond.enforceIsContractOwner();\r\n Storage storage s = getStorage();\r\n s.cbSlippage = _newSlippage;\r\n emit CBUpdatedSlippageTolerance(_newSlippage);\r\n }\r\n\r\n function cbUpdateBridge(address _newAddress) external {\r\n LibDiamond.enforceIsContractOwner();\r\n if (_newAddress == address(0)) revert ZeroAddressProvided();\r\n Storage storage s = getStorage();\r\n s.cbBridge = _newAddress;\r\n emit CBUpdatedBridge(_newAddress);\r\n }\r\n\r\n //////////////////////////////////////////////////////////////\r\n ////////////////////// Private Functions /////////////////////\r\n //////////////////////////////////////////////////////////////\r\n\r\n /// @dev fetch local storage\r\n function getStorage() private pure returns (Storage storage s) {\r\n bytes32 namespace = NAMESPACE;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n s.slot := namespace\r\n }\r\n }\r\n}\r\n" + }, + "src/bridges/interfaces/ICBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\ninterface ICBridge {\r\n function send(\r\n address _receiver,\r\n address _token,\r\n uint256 _amount,\r\n uint64 _dstChinId,\r\n uint64 _nonce,\r\n uint32 _maxSlippage\r\n ) external;\r\n\r\n function sendNative(\r\n address _receiver,\r\n uint256 _amount,\r\n uint64 _dstChinId,\r\n uint64 _nonce,\r\n uint32 _maxSlippage\r\n ) external payable;\r\n\r\n function relay(\r\n bytes calldata _relayRequest,\r\n bytes[] calldata _sigs,\r\n address[] calldata _signers,\r\n uint256[] calldata _powers\r\n ) external;\r\n}\r\n" + }, + "src/bridges/errors/CBridgeErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\nerror CBSlippageTooLow();\r\n" + }, + "src/bridges/facets/HopFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.4;\r\n\r\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport { IHopBridge } from \"../interfaces/IHopBridge.sol\";\r\nimport { LibAsset } from \"../libs/LibAsset.sol\";\r\nimport { LibDiamond } from \"../libs/LibDiamond.sol\";\r\nimport { ReentrancyGuard } from \"../../common/helpers/DiamondReentrancyGuard.sol\";\r\nimport {\r\n InvalidAmount,\r\n InvalidBridgeConfigLength,\r\n CannotBridgeToSameNetwork,\r\n NativeValueWithERC,\r\n InvalidConfig\r\n} from \"../errors/GenericErrors.sol\";\r\n\r\n/**\r\n * @title Hop Protocol Integration\r\n *\r\n * @notice Contract which provides bridging functionality through Hop Protocol\r\n *\r\n */\r\ncontract HopFacet is ReentrancyGuard {\r\n // storage\r\n\r\n bytes32 internal constant NAMESPACE = keccak256(\"io.etherspot.facets.hop\");\r\n struct Storage {\r\n uint256 chainLayerId;\r\n }\r\n\r\n // types\r\n\r\n struct HopData {\r\n address bridge;\r\n address ammWrapper;\r\n address asset;\r\n address recipient;\r\n uint256 chainId;\r\n uint256 amount;\r\n uint256 bonderFee;\r\n uint256 amountOutMin;\r\n uint256 deadline;\r\n uint256 destinationAmountOutMin;\r\n uint256 destinationDeadline;\r\n }\r\n\r\n // events\r\n\r\n /**\r\n * @dev Emitted when facet initializes\r\n * @param chainId current chain id\r\n * @param chainLayerId current chain layer id\r\n */\r\n event HopInitialized(\r\n uint256 chainId,\r\n uint256 chainLayerId\r\n );\r\n\r\n /**\r\n * @dev Emitted on token swap\r\n * @param _destination destination chain id\r\n * @param _bridge address of the bridge on chain _destination,\r\n * @param _ammWrapper address of the amm wrapper,\r\n * @param _recipient recipient\r\n * @param _asset address of the asset\r\n * @param _amount amount of assets\r\n * @param _bonderFee fee\r\n * @param _amountOutMin The minimum amount received after attempting to\r\n * swap in the destination\r\n * @param _deadline The deadline for swapping in the destination AMM market.\r\n * 0 if no * swap is intended.\r\n * @param _destinationAmountOutMin The minimum amount of tokens to receive after bridging\r\n * @param _destinationDeadline The time the transaction must be completed\r\n */\r\n event HopTokenSwap(\r\n uint256 indexed _destination,\r\n address _bridge,\r\n address _ammWrapper,\r\n address indexed _recipient,\r\n address indexed _asset,\r\n uint256 _amount,\r\n uint256 _bonderFee,\r\n uint256 _amountOutMin,\r\n uint256 _deadline,\r\n uint256 _destinationAmountOutMin,\r\n uint256 _destinationDeadline\r\n );\r\n\r\n\r\n\r\n // external functions\r\n\r\n /**\r\n * @notice Initializes local variables for the Connext facet\r\n */\r\n function initHop(uint256 _chainLayerId) external {\r\n LibDiamond.enforceIsContractOwner();\r\n\r\n Storage storage s = getStorage();\r\n s.chainLayerId = _chainLayerId;\r\n\r\n emit HopInitialized(\r\n getChainID(),\r\n _chainLayerId\r\n );\r\n }\r\n\r\n /**\r\n * @notice Bridges tokens via Hop Protocol\r\n * @param _hopData data specific to Hop Protocol\r\n */\r\n function hopTokenTransfer(\r\n HopData calldata _hopData\r\n ) external payable nonReentrant {\r\n LibAsset.depositAsset(_hopData.asset, _hopData.amount);\r\n\r\n address bridge;\r\n if (getLayerId() == 1) {\r\n bridge = _hopData.bridge;\r\n } else {\r\n bridge = _hopData.ammWrapper;\r\n }\r\n\r\n if (getChainID() == _hopData.chainId)\r\n revert CannotBridgeToSameNetwork();\r\n\r\n // Give Hop approval to bridge tokens\r\n LibAsset.maxApproveERC20(\r\n IERC20(_hopData.asset),\r\n bridge,\r\n _hopData.amount\r\n );\r\n\r\n uint256 value = LibAsset.isNativeAsset(_hopData.asset)\r\n ? _hopData.amount\r\n : 0;\r\n\r\n if (getLayerId() == 1) {\r\n // Ethereum L1\r\n IHopBridge(bridge).sendToL2{value: value}(\r\n _hopData.chainId,\r\n _hopData.recipient,\r\n _hopData.amount,\r\n _hopData.destinationAmountOutMin,\r\n _hopData.destinationDeadline,\r\n address(0),\r\n 0\r\n );\r\n } else {\r\n // L2\r\n IHopBridge(bridge).swapAndSend{value: value}(\r\n _hopData.chainId,\r\n _hopData.recipient,\r\n _hopData.amount,\r\n _hopData.bonderFee,\r\n _hopData.amountOutMin,\r\n _hopData.deadline,\r\n _hopData.destinationAmountOutMin,\r\n _hopData.destinationDeadline\r\n );\r\n }\r\n emit HopTokenSwap(\r\n _hopData.chainId,\r\n _hopData.bridge,\r\n _hopData.ammWrapper,\r\n _hopData.recipient,\r\n _hopData.asset,\r\n _hopData.amount,\r\n _hopData.bonderFee,\r\n _hopData.amountOutMin,\r\n _hopData.deadline,\r\n _hopData.destinationAmountOutMin,\r\n _hopData.destinationDeadline\r\n );\r\n }\r\n\r\n /// private Methods ///\r\n\r\n /**\r\n * @dev returns local storage\r\n */\r\n function getStorage() private pure returns (Storage storage s) {\r\n bytes32 namespace = NAMESPACE;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n s.slot := namespace\r\n }\r\n }\r\n\r\n /**\r\n * @dev returns current chain layer number\r\n * @return uint256 layer number\r\n */\r\n function getLayerId() private view returns (uint256) {\r\n return getStorage().chainLayerId;\r\n }\r\n\r\n /**\r\n * @dev fetch chain id\r\n */\r\n function getChainID() private view returns (uint256) {\r\n uint256 id;\r\n // solhint-disable-next-line no-inline-assembly\r\n assembly {\r\n id := chainid()\r\n }\r\n return id;\r\n }\r\n}\r\n" + }, + "src/bridges/interfaces/IHopBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.4;\r\n\r\ninterface IHopBridge {\r\n function sendToL2(\r\n uint256 chainId,\r\n address recipient,\r\n uint256 amount,\r\n uint256 amountOutMin,\r\n uint256 deadline,\r\n address relayer,\r\n uint256 relayerFee\r\n ) external payable;\r\n\r\n function swapAndSend(\r\n uint256 chainId,\r\n address recipient,\r\n uint256 amount,\r\n uint256 bonderFee,\r\n uint256 amountOutMin,\r\n uint256 deadline,\r\n uint256 destinationAmountOutMin,\r\n uint256 destinationDeadline\r\n ) external payable;\r\n}\r\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/fuji/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json b/deployments/fuji/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json new file mode 100644 index 00000000..fa380d29 --- /dev/null +++ b/deployments/fuji/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json @@ -0,0 +1,142 @@ +{ + "language": "Solidity", + "sources": { + "src/payments/PaymentRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./PaymentDepositAccount.sol\";\n\n\n/**\n * @title Payment registry\n *\n * @notice A registry for payment and payment channels\n *\n * @dev the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message.\n * Process will be rejected when any of senders channels will be committed.\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct Deposit {\n address account;\n mapping(address => uint256) withdrawnAmount;\n mapping(address => uint256) exitLockedUntil;\n }\n\n struct PaymentChannel {\n uint256 committedAmount;\n }\n\n struct DepositWithdrawal {\n address owner;\n address token;\n uint256 amount;\n }\n\n struct PaymentChannelCommit {\n address sender;\n address recipient;\n address token;\n bytes32 uid;\n uint256 blockNumber;\n uint256 amount;\n }\n\n uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;\n\n bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(\n \"DepositWithdrawal(address owner,address token,uint256 amount)\"\n );\n bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(\n \"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n uint256 public depositExitLockPeriod;\n\n mapping(address => Deposit) private deposits;\n mapping(bytes32 => PaymentChannel) private paymentChannels;\n\n // events\n\n /**\n * @dev Emitted when the deposit account is deployed\n * @param depositAccount deposit account address\n * @param owner owner address\n */\n event DepositAccountDeployed(\n address depositAccount,\n address owner\n );\n\n /**\n * @dev Emitted when the deposit exist is requested\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param lockedUntil deposit exist locked util time\n */\n event DepositExitRequested(\n address depositAccount,\n address owner,\n address token,\n uint256 lockedUntil\n );\n\n /**\n * @dev Emitted when the deposit exist is completed\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount deposit exist amount\n */\n event DepositExitCompleted(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the deposit exist is rejected\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n */\n event DepositExitRejected(\n address depositAccount,\n address owner,\n address token\n );\n\n /**\n * @dev Emitted when the deposit has been withdrawn\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount withdrawn amount\n */\n event DepositWithdrawn(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment channel has been committed\n * @param hash channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @param amount committed amount\n */\n event PaymentChannelCommitted(\n bytes32 hash,\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentWithdrawn(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been deposited\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentDeposited(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn and deposited (split)\n * @param channelHash channel hash\n * @param totalValue payment total value\n * @param depositValue payment deposited value\n */\n event PaymentSplit(\n bytes32 channelHash,\n uint256 totalValue,\n uint256 depositValue\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initialize `PaymentRegistry` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n * @param depositExitLockPeriod_ deposit exit lock period\n * @param guardians_ array of guardians addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_,\n uint256 depositExitLockPeriod_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n if (depositExitLockPeriod_ == 0) {\n depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;\n } else {\n depositExitLockPeriod = depositExitLockPeriod_;\n }\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Deploys deposit account\n * @param owner owner address\n */\n function deployDepositAccount(\n address owner\n )\n external\n {\n _deployDepositAccount(owner);\n }\n\n /**\n * @notice Requests deposit exit\n * @param token token address\n */\n function requestDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil == 0,\n \"PaymentRegistry: deposit exit already requested\"\n );\n\n _deployDepositAccount(owner);\n\n // solhint-disable-next-line not-rely-on-time\n lockedUntil = now.add(depositExitLockPeriod);\n\n deposits[owner].exitLockedUntil[token] = lockedUntil;\n\n emit DepositExitRequested(\n deposits[owner].account,\n owner,\n token,\n lockedUntil\n );\n }\n\n /**\n * @notice Processes deposit exit\n * @param token token address\n */\n function processDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil != 0,\n \"PaymentRegistry: deposit exit not requested\"\n );\n\n require(\n // solhint-disable-next-line not-rely-on-time\n lockedUntil <= now,\n \"PaymentRegistry: deposit exit locked\"\n );\n\n deposits[owner].exitLockedUntil[token] = 0;\n\n address depositAccount = deposits[owner].account;\n uint256 depositValue;\n\n if (token == address(0)) {\n depositValue = depositAccount.balance;\n } else {\n depositValue = ERC20Token(token).balanceOf(depositAccount);\n }\n\n _transferFromDeposit(\n depositAccount,\n owner,\n token,\n depositValue\n );\n\n emit DepositExitCompleted(\n depositAccount,\n owner,\n token,\n depositValue\n );\n }\n\n /**\n * @notice Withdraws deposit\n * @param token token address\n * @param amount amount to withdraw\n * @param guardianSignature guardian signature\n */\n function withdrawDeposit(\n address token,\n uint256 amount,\n bytes calldata guardianSignature\n )\n external\n {\n address owner = _getContextAccount();\n uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);\n\n require(\n value > 0,\n \"PaymentRegistry: invalid amount\"\n );\n\n bytes32 messageHash = _hashDepositWithdrawal(\n owner,\n token,\n amount\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n deposits[owner].withdrawnAmount[token] = amount;\n\n _verifyDepositExitOrDeployAccount(owner, token);\n\n _transferFromDeposit(\n deposits[owner].account,\n owner,\n token,\n value\n );\n\n emit DepositWithdrawn(\n deposits[owner].account,\n owner,\n token,\n amount\n );\n }\n\n /**\n * @notice Commits payment channel and withdraw payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndWithdraw(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue\n );\n\n emit PaymentWithdrawn(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel and deposit payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndDeposit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(recipient),\n token,\n paymentValue\n );\n\n emit PaymentDeposited(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel, withdraws and deposits (split) payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param depositPaymentValue amount to deposit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndSplit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n uint256 depositPaymentValue,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferSplitFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue,\n depositPaymentValue\n );\n\n emit PaymentSplit(hash, paymentValue, depositPaymentValue);\n }\n\n // external functions (views)\n\n /**\n * @notice Computes deposit account address\n * @param owner owner address\n * @return deposit account address\n */\n function computeDepositAccountAddress(\n address owner\n )\n external\n view\n returns (address)\n {\n return _computeDepositAccountAddress(owner);\n }\n\n /**\n * @notice Checks if deposit account is deployed\n * @param owner owner address\n * @return true when deposit account is deployed\n */\n function isDepositAccountDeployed(\n address owner\n )\n external\n view\n returns (bool)\n {\n return deposits[owner].account != address(0);\n }\n\n /**\n * @notice Gets deposit exit locked until time\n * @param owner owner address\n * @param token token address\n * @return locked until time\n */\n function getDepositExitLockedUntil(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].exitLockedUntil[token];\n }\n\n /**\n * @notice Gets deposit withdrawn amount\n * @param owner owner address\n * @param token token address\n * @return withdrawn amount\n */\n function getDepositWithdrawnAmount(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].withdrawnAmount[token];\n }\n\n /**\n * @notice Gets payment channel committed amount\n * @param hash payment channel hash\n * @return committed amount\n */\n function getPaymentChannelCommittedAmount(\n bytes32 hash\n )\n external\n view\n returns (uint256)\n {\n return paymentChannels[hash].committedAmount;\n }\n\n // external functions (pure)\n\n /**\n * @notice Computes payment channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @return hash\n */\n function computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n external\n pure\n returns (bytes32)\n {\n return _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DepositWithdrawal` message payload\n * @param depositWithdrawal struct\n * @return hash\n */\n function hashDepositWithdrawal(\n DepositWithdrawal memory depositWithdrawal\n )\n public\n view\n returns (bytes32)\n {\n return _hashDepositWithdrawal(\n depositWithdrawal.owner,\n depositWithdrawal.token,\n depositWithdrawal.amount\n );\n }\n\n /**\n * @notice Hashes `PaymentChannelCommit` message payload\n * @param paymentChannelCommit struct\n * @return hash\n */\n function hashPaymentChannelCommit(\n PaymentChannelCommit memory paymentChannelCommit\n )\n public\n view\n returns (bytes32)\n {\n return _hashPaymentChannelCommit(\n paymentChannelCommit.sender,\n paymentChannelCommit.recipient,\n paymentChannelCommit.token,\n paymentChannelCommit.uid,\n paymentChannelCommit.blockNumber,\n paymentChannelCommit.amount\n );\n }\n\n // private functions\n\n function _deployDepositAccount(\n address owner\n )\n private\n {\n if (deposits[owner].account == address(0)) {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());\n\n emit DepositAccountDeployed(\n deposits[owner].account,\n owner\n );\n }\n }\n\n function _verifyDepositExitOrDeployAccount(\n address owner,\n address token\n )\n private\n {\n if (deposits[owner].exitLockedUntil[token] > 0) {\n deposits[owner].exitLockedUntil[token] = 0;\n\n emit DepositExitRejected(\n deposits[owner].account,\n owner,\n token\n );\n } else {\n _deployDepositAccount(owner);\n }\n }\n\n function _commitPaymentChannel(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes memory senderSignature,\n bytes memory guardianSignature\n )\n private\n returns (bytes32 hash, address depositAccount, uint256 paymentValue)\n {\n bytes32 messageHash = _hashPaymentChannelCommit(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n );\n\n if (senderSignature.length == 0) {\n require(\n externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),\n \"PaymentRegistry: invalid guardian signature\"\n );\n } else {\n address signer = messageHash.recoverAddress(senderSignature);\n\n if (sender != signer) {\n require(\n personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||\n externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),\n \"PaymentRegistry: invalid sender signature\"\n );\n }\n }\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n hash = _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n\n /// @dev calc payment value\n paymentValue = amount.sub(paymentChannels[hash].committedAmount);\n\n require(\n paymentValue != 0,\n \"PaymentRegistry: invalid payment value\"\n );\n\n paymentChannels[hash].committedAmount = amount;\n\n _verifyDepositExitOrDeployAccount(sender, token);\n\n depositAccount = deposits[sender].account;\n\n emit PaymentChannelCommitted(\n hash,\n sender,\n recipient,\n token,\n uid,\n amount\n );\n\n return (hash, depositAccount, paymentValue);\n }\n\n function _transferFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 value\n )\n private\n {\n if (token == address(0)) {\n PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n to,\n value,\n new bytes(0)\n );\n } else {\n bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n token,\n 0,\n abi.encodeWithSelector(\n ERC20Token(token).transfer.selector,\n to,\n value\n )\n );\n\n if (response.length > 0) {\n require(\n abi.decode(response, (bool)),\n \"PaymentRegistry: ERC20Token transfer reverted\"\n );\n }\n }\n }\n\n function _transferSplitFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 paymentValue,\n uint256 depositValue\n )\n private\n {\n require(\n depositValue > 0,\n \"PaymentRegistry: invalid deposit value\"\n );\n\n uint256 withdrawValue = paymentValue.sub(depositValue);\n\n require(\n withdrawValue > 0,\n \"PaymentRegistry: invalid withdraw value\"\n );\n\n _transferFromDeposit(\n depositAccount,\n to,\n token,\n withdrawValue\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(to),\n token,\n depositValue\n );\n }\n\n // private functions (views)\n\n function _computeDepositAccountAddress(\n address owner\n )\n private\n view\n returns (address)\n {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n bytes memory creationCode = type(PaymentDepositAccount).creationCode;\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 function _hashDepositWithdrawal(\n address owner,\n address token,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(\n owner,\n token,\n amount\n ));\n }\n\n function _hashPaymentChannelCommit(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n ));\n }\n\n // private functions (pure)\n\n function _computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n private\n pure\n returns (bytes32)\n {\n return keccak256(\n abi.encodePacked(\n sender,\n recipient,\n token,\n uid\n )\n );\n }\n}\n" + }, + "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ław Głogowski \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" + }, + "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" + }, + "src/common/libs/SafeMathLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n" + }, + "src/common/lifecycle/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski \n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n" + }, + "src/common/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ław Głogowski \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" + }, + "src/common/token/ERC20Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n" + }, + "src/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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "src/gateway/GatewayRecipient.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n" + }, + "src/payments/PaymentDepositAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/access/Controlled.sol\";\n\n\n/**\n * @title Payment deposit account\n *\n * @dev Simple account contract with only one method - `executeTransaction`\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentDepositAccount is Controlled {\n /**\n * @dev Public constructor\n */\n constructor() public payable Controlled() {}\n\n /**\n * @notice Allow receives\n */\n receive()\n external\n payable\n {\n //\n }\n\n // external functions\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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \n */\ncontract AccountBase {\n address public registry;\n}\n" + }, + "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" + }, + "src/common/libs/BytesLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski \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" + }, + "src/tokens/WrappedWeiToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski \n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n" + }, + "src/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 \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" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.12;\r\npragma experimental ABIEncoderV2;\r\n\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/**\r\n * @title Gateway\r\n *\r\n * @notice GSN replacement\r\n *\r\n * @author Stanisław Głogowski \r\n */\r\ncontract Gateway is Initializable, SignatureValidator {\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\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 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 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 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 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 // 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}" + }, + "src/ens/ENSController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./resolvers/ENSPubKeyResolver.sol\";\nimport \"./resolvers/ENSTextResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n\n/**\n * @title ENS controller\n *\n * @notice ENS subnode registrar\n *\n * @dev The process of adding root node consists of 3 steps:\n * 1. `submitNode` - should be called from ENS node owner,\n * 2. Change ENS node owner in ENS registry to ENS controller,\n * 3. `verifyNode` - should be called from previous ENS node owner,\n *\n * To register sub node, `msg.sender` need to send valid signature from one of guardian key.\n * Once registration is complete `msg.sender` becoming both node owner and `addr` record value.\n *\n * After registration sub node cannot be replaced.\n *\n * @author Stanisław Głogowski \n */\ncontract ENSController is Guarded, Initializable, SignatureValidator, GatewayRecipient, ENSAddressResolver, ENSNameResolver, ENSPubKeyResolver, ENSTextResolver {\n struct SubNodeRegistration {\n address account;\n bytes32 node;\n bytes32 label;\n }\n\n bytes4 private constant INTERFACE_META_ID = bytes4(keccak256(abi.encodePacked(\"supportsInterface(bytes4)\")));\n\n bytes32 private constant HASH_PREFIX_SUB_NODE_REGISTRATION = keccak256(\n \"SubNodeRegistration(address account,bytes32 node,bytes32 label)\"\n );\n\n ENSRegistry public registry;\n\n mapping(bytes32 => address) public nodeOwners;\n\n // events\n\n /**\n * @dev Emitted when new node is submitted\n * @param node node name hash\n * @param owner owner address\n */\n event NodeSubmitted(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when the existing owner is verified\n * @param node node name hash\n */\n event NodeVerified(\n bytes32 node\n );\n\n /**\n * @dev Emitted when new node is released\n * @param node node name hash\n * @param owner owner address\n */\n event NodeReleased(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when ENS registry address is changed\n * @param registry registry address\n */\n event RegistryChanged(\n address registry\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Guarded() Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSController` contract\n * @param registry_ ENS registry address\n * @param gateway_ gateway address\n */\n function initialize(\n ENSRegistry registry_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n registry = registry_;\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Sets registry\n * @param registry_ registry address\n */\n function setRegistry(\n ENSRegistry registry_\n )\n external\n onlyGuardian\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n require(\n registry_ != registry,\n \"ENSController: registry already set\"\n );\n\n registry = registry_;\n\n emit RegistryChanged(\n address(registry)\n );\n }\n\n /**\n * @notice Submits node\n * @dev Should be called from the current ENS node owner\n * @param node node name hash\n */\n function submitNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == address(0),\n \"ENSController: node already submitted\"\n );\n\n require(\n registry.owner(node) == owner,\n \"ENSController: invalid ens node owner\"\n );\n\n nodeOwners[node] = owner;\n\n emit NodeSubmitted(node, owner);\n }\n\n /**\n * @notice Verifies node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function verifyNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n require(\n registry.owner(node) == address(this),\n \"ENSController: invalid ens node owner\"\n );\n\n _setAddr(node, address(this));\n\n registry.setResolver(node, address(this));\n\n emit NodeVerified(node);\n }\n\n /**\n * @notice Releases node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function releaseNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(this),\n \"ENSController: node doesn't exist\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n registry.setOwner(node, owner);\n\n delete nodeOwners[node];\n\n emit NodeReleased(node, owner);\n }\n\n /**\n * @notice Sync address\n * @param node node name hash\n */\n function syncAddr(\n bytes32 node\n )\n external\n {\n address account = _getContextAccount();\n\n require(\n account == registry.owner(node),\n \"ENSController: caller is not the node owner\"\n );\n\n require(\n registry.resolver(node) == address(this),\n \"ENSController: invalid node resolver\"\n );\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already in sync\"\n );\n\n _setAddr(node, account);\n }\n\n /**\n * @notice Registers sub node\n * @param node node name hash\n * @param label label hash\n * @param guardianSignature guardian signature\n */\n function registerSubNode(\n bytes32 node,\n bytes32 label,\n bytes calldata guardianSignature\n )\n external\n {\n address account = _getContextAccount();\n\n bytes32 messageHash = _hashSubNodeRegistration(\n account,\n node,\n label\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"ENSController: invalid guardian signature\"\n );\n\n bytes32 subNode = keccak256(\n abi.encodePacked(\n node,\n label\n )\n );\n\n require(\n _addr(node) == address(this),\n \"ENSController: invalid node\"\n );\n\n require(\n _addr(subNode) == address(0),\n \"ENSController: label already taken\"\n );\n\n registry.setSubnodeRecord(node, label, address(this), address(this), 0);\n registry.setOwner(subNode, account);\n\n _setAddr(subNode, account);\n }\n\n // external functions (pure)\n function supportsInterface(\n bytes4 interfaceID\n )\n external\n pure\n returns(bool)\n {\n return interfaceID == INTERFACE_META_ID ||\n interfaceID == INTERFACE_ADDR_ID ||\n interfaceID == INTERFACE_ADDRESS_ID ||\n interfaceID == INTERFACE_NAME_ID ||\n interfaceID == INTERFACE_PUB_KEY_ID ||\n interfaceID == INTERFACE_TEXT_ID;\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `SubNodeRegistration` message payload\n * @param subNodeRegistration struct\n * @return hash\n */\n function hashSubNodeRegistration(\n SubNodeRegistration memory subNodeRegistration\n )\n public\n view\n returns (bytes32)\n {\n return _hashSubNodeRegistration(\n subNodeRegistration.account,\n subNodeRegistration.node,\n subNodeRegistration.label\n );\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n override\n view\n returns (bool)\n {\n return registry.owner(node) == _getContextAccount();\n }\n\n // private functions (views)\n\n function _hashSubNodeRegistration(\n address account,\n bytes32 node,\n bytes32 label\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_SUB_NODE_REGISTRATION, abi.encodePacked(\n account,\n node,\n label\n ));\n }\n}\n" + }, + "src/ens/resolvers/ENSAddressResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract address resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/AddrResolver.sol\n */\nabstract contract ENSAddressResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_ADDR_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32)\")));\n bytes4 internal constant INTERFACE_ADDRESS_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32,uint)\")));\n\n uint internal constant COIN_TYPE_ETH = 60;\n\n mapping(bytes32 => mapping(uint => bytes)) internal resolverAddresses;\n\n // events\n\n event AddrChanged(\n bytes32 indexed node,\n address addr\n );\n\n event AddressChanged(\n bytes32 indexed node,\n uint coinType,\n bytes newAddress\n );\n\n // external functions\n\n function setAddr(\n bytes32 node,\n address addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, addr_);\n }\n\n function setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, coinType, addr_);\n }\n\n // external functions (views)\n\n function addr(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return _addr(node);\n }\n\n function addr(\n bytes32 node,\n uint coinType\n )\n external\n view\n returns (bytes memory)\n {\n return resolverAddresses[node][coinType];\n }\n\n // internal functions\n\n function _setAddr(\n bytes32 node,\n address addr_\n )\n internal\n {\n _setAddr(node, COIN_TYPE_ETH, _addressToBytes(addr_));\n }\n\n function _setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n internal\n {\n emit AddressChanged(node, coinType, addr_);\n\n if(coinType == COIN_TYPE_ETH) {\n emit AddrChanged(node, _bytesToAddress(addr_));\n }\n\n resolverAddresses[node][coinType] = addr_;\n }\n\n // internal functions (views)\n\n function _addr(\n bytes32 node\n )\n internal\n view\n returns (address)\n {\n address result;\n\n bytes memory addr_ = resolverAddresses[node][COIN_TYPE_ETH];\n\n if (addr_.length > 0) {\n result = _bytesToAddress(addr_);\n }\n\n return result;\n }\n\n // private function (pure)\n\n function _bytesToAddress(\n bytes memory data\n )\n private\n pure\n returns(address payable)\n {\n address payable result;\n\n require(data.length == 20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 32)), exp(256, 12))\n }\n\n return result;\n }\n\n function _addressToBytes(\n address addr_\n )\n private\n pure\n returns(bytes memory)\n {\n bytes memory result = new bytes(20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(add(result, 32), mul(addr_, exp(256, 12)))\n }\n\n return result;\n }\n}\n" + }, + "src/ens/resolvers/ENSNameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract name resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/NameResolver.sol\n */\nabstract contract ENSNameResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_NAME_ID = bytes4(keccak256(abi.encodePacked(\"name(bytes32)\")));\n\n mapping(bytes32 => string) internal resolverNames;\n\n // events\n\n event NameChanged(\n bytes32 indexed node,\n string name\n );\n\n // external functions\n\n function setName(\n bytes32 node,\n string calldata name\n )\n external\n onlyNodeOwner(node)\n {\n resolverNames[node] = name;\n\n emit NameChanged(node, name);\n }\n\n // external functions (views)\n\n function name(\n bytes32 node\n )\n external\n view\n returns (string memory)\n {\n return resolverNames[node];\n }\n}\n" + }, + "src/ens/resolvers/ENSPubKeyResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract pub key resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/PubkeyResolver.sol\n */\nabstract contract ENSPubKeyResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_PUB_KEY_ID = bytes4(keccak256(abi.encodePacked(\"pubkey(bytes32)\")));\n\n struct PubKey {\n bytes32 x;\n bytes32 y;\n }\n\n mapping(bytes32 => PubKey) internal resolverPubKeys;\n\n // events\n\n event PubkeyChanged(\n bytes32 indexed node,\n bytes32 x,\n bytes32 y\n );\n\n // external functions (views)\n\n function setPubkey(\n bytes32 node,\n bytes32 x,\n bytes32 y\n )\n external\n onlyNodeOwner(node)\n {\n resolverPubKeys[node] = PubKey(x, y);\n\n emit PubkeyChanged(node, x, y);\n }\n\n // external functions (views)\n\n function pubkey(\n bytes32 node\n )\n external\n view\n returns (bytes32 x, bytes32 y)\n {\n return (resolverPubKeys[node].x, resolverPubKeys[node].y);\n }\n}\n" + }, + "src/ens/resolvers/ENSTextResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract text resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/TextResolver.sol\n */\nabstract contract ENSTextResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_TEXT_ID = bytes4(keccak256(abi.encodePacked(\"text(bytes32,string)\")));\n\n mapping(bytes32 => mapping(string => string)) internal resolverTexts;\n\n // events\n\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key\n );\n\n // external functions (views)\n\n function setText(\n bytes32 node,\n string calldata key,\n string calldata value\n )\n external\n onlyNodeOwner(node)\n {\n resolverTexts[node][key] = value;\n\n emit TextChanged(node, key, key);\n }\n\n // external functions (views)\n\n function text(\n bytes32 node,\n string calldata key\n )\n external\n view\n returns (string memory)\n {\n return resolverTexts[node][key];\n }\n}\n" + }, + "src/ens/ENSRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS registry\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\n */\ncontract ENSRegistry {\n struct Record {\n address owner;\n address resolver;\n uint64 ttl;\n }\n\n mapping (bytes32 => Record) private records;\n mapping (address => mapping(address => bool)) private operators;\n\n // events\n\n event NewOwner(\n bytes32 indexed node,\n bytes32 indexed label,\n address owner\n );\n\n event Transfer(\n bytes32 indexed node,\n address owner\n );\n\n event NewResolver(\n bytes32 indexed node,\n address resolver\n );\n\n event NewTTL(\n bytes32 indexed node,\n uint64 ttl\n );\n\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n // modifiers\n\n modifier authorised(\n bytes32 node\n )\n {\n address owner = records[node].owner;\n\n require(\n owner == msg.sender || operators[owner][msg.sender],\n \"ENSRegistry: reverted by authorised modifier\"\n );\n\n _;\n }\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n {\n // solhint-disable-next-line avoid-tx-origin\n records[0x0].owner = tx.origin;\n }\n\n // external functions\n\n function setRecord(\n bytes32 node,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n setOwner(node, owner_);\n\n _setResolverAndTTL(node, resolver_, ttl_);\n }\n\n function setTTL(\n bytes32 node,\n uint64 ttl_\n )\n external\n authorised(node)\n {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n bytes32 subNode = setSubnodeOwner(node, label, owner_);\n\n _setResolverAndTTL(subNode, resolver_, ttl_);\n }\n\n function setApprovalForAll(\n address operator,\n bool approved\n )\n external\n {\n operators[msg.sender][operator] = approved;\n\n emit ApprovalForAll(\n msg.sender,\n operator,\n approved\n );\n }\n\n // external functions (views)\n\n function owner(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n address addr = records[node].owner;\n\n if (addr == address(this)) {\n return address(0x0);\n }\n\n return addr;\n }\n\n function resolver(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return records[node].resolver;\n }\n\n function ttl(\n bytes32 node\n )\n external\n view\n returns (uint64)\n {\n return records[node].ttl;\n }\n\n function recordExists(\n bytes32 node\n )\n external\n view\n returns (bool)\n {\n return records[node].owner != address(0x0);\n }\n\n function isApprovedForAll(\n address owner_,\n address operator\n )\n external\n view\n returns (bool)\n {\n return operators[owner_][operator];\n }\n\n // public functions\n\n function setOwner(\n bytes32 node,\n address owner_\n )\n public\n authorised(node)\n {\n records[node].owner = owner_;\n\n emit Transfer(node, owner_);\n }\n\n function setResolver(\n bytes32 node,\n address resolver_\n )\n public\n authorised(node)\n {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner_\n )\n public\n authorised(node)\n returns(bytes32)\n {\n bytes32 subNode = keccak256(abi.encodePacked(node, label));\n\n records[subNode].owner = owner_;\n\n emit NewOwner(node, label, owner_);\n\n return subNode;\n }\n\n // private functions\n\n function _setResolverAndTTL(\n bytes32 node,\n address resolver_,\n uint64 ttl_\n )\n private\n {\n if (resolver_ != records[node].resolver) {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n if (ttl_ != records[node].ttl) {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n }\n}\n" + }, + "src/ens/resolvers/ENSAbstractResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS abstract resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/ResolverBase.sol\n */\nabstract contract ENSAbstractResolver {\n // modifiers\n\n modifier onlyNodeOwner(bytes32 node)\n {\n require(\n _isNodeOwner(node),\n \"ENSAbstractResolver: reverted by onlyNodeOwner modifier\"\n );\n\n _;\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n virtual\n view\n returns (bool);\n}\n" + }, + "src/ens/ENSReverseRegistrar.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/AddressLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS reverse registrar\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\n */\ncontract ENSReverseRegistrar is Initializable {\n using AddressLib for address;\n\n // namehash('addr.reverse')\n bytes32 public constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n ENSRegistry public registry;\n ENSNameResolver public resolver;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSReverseRegistrar` contract\n * @param registry_ ENS registry address\n * @param resolver_ ENS name resolver address\n */\n function initialize(\n ENSRegistry registry_,\n ENSNameResolver resolver_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n resolver = resolver_;\n }\n\n // external functions\n\n function claim(\n address owner\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, address(0));\n }\n\n function claimWithResolver(\n address owner,\n address resolver_\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, resolver_);\n }\n\n function setName(\n string memory name\n )\n public\n returns (bytes32)\n {\n bytes32 node = _claimWithResolver(address(this), address(resolver));\n\n resolver.setName(node, name);\n\n return node;\n }\n\n // external functions (pure)\n\n function node(\n address addr_\n )\n external\n pure\n returns (bytes32)\n {\n return keccak256(abi.encodePacked(ADDR_REVERSE_NODE, addr_.toSha3Hash()));\n }\n\n // private functions\n\n function _claimWithResolver(\n address owner,\n address resolver_\n )\n private\n returns (bytes32)\n {\n bytes32 label = address(msg.sender).toSha3Hash();\n bytes32 node_ = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n address currentOwner = registry.owner(node_);\n\n if (resolver_ != address(0x0) && resolver_ != registry.resolver(node_)) {\n if (currentOwner != address(this)) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this));\n currentOwner = address(this);\n }\n\n registry.setResolver(node_, resolver_);\n }\n\n // Update the owner if required\n if (currentOwner != owner) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);\n }\n\n return node_;\n }\n}\n" + }, + "src/common/libs/AddressLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Address library\n */\nlibrary AddressLib {\n /**\n * @notice Converts address into sha3 hash\n * @param self address\n * @return sha3 hash\n */\n function toSha3Hash(\n address self\n )\n internal\n pure\n returns (bytes32)\n {\n bytes32 result;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000\n\n for { let i := 40 } gt(i, 0) { } {\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n }\n\n result := keccak256(0, 40)\n }\n\n return result;\n }\n}\n" + }, + "src/ens/ENSHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS helper\n *\n * @author Stanisław Głogowski \n */\ncontract ENSHelper is Initializable {\n ENSRegistry public registry;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSLookupHelper` contract\n * @param registry_ ENS registry address\n */\n function initialize(\n ENSRegistry registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n /**\n * @notice Gets nodes addresses\n * @param nodes array of nodes\n * @return nodes addresses\n */\n function getAddresses(\n bytes32[] memory nodes\n )\n external\n view\n returns (address[] memory)\n {\n uint nodesLen = nodes.length;\n address[] memory result = new address[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getAddress(nodes[i]);\n }\n\n return result;\n }\n\n /**\n * @notice Gets nodes names\n * @param nodes array of nodes\n * @return nodes names\n */\n function getNames(\n bytes32[] memory nodes\n )\n external\n view\n returns (string[] memory)\n {\n uint nodesLen = nodes.length;\n string[] memory result = new string[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getName(nodes[i]);\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getAddress(\n bytes32 node\n )\n private\n view\n returns (address)\n {\n address result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSAddressResolver(resolver).addr(node) returns (address addr) {\n result = addr;\n } catch {\n //\n }\n }\n\n return result;\n }\n\n function _getName(\n bytes32 node\n )\n private\n view\n returns (string memory)\n {\n string memory result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSNameResolver(resolver).name(node) returns (string memory name) {\n result = name;\n } catch {\n //\n }\n }\n\n return result;\n }\n}\n" + }, + "src/common/account/AccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../lifecycle/Initializable.sol\";\nimport \"./AccountBase.sol\";\nimport \"./AccountRegistry.sol\";\n\n\n/**\n * @title Account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1 is Initializable, AccountBase {\n bytes32 constant private ERC777_TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(abi.encodePacked(\"ERC777TokensRecipient\"));\n bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n bytes4 constant private ERC1271_VALID_MESSAGE_HASH_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes32,bytes)\")));\n bytes4 constant private ERC1271_VALID_MESSAGE_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes,bytes)\")));\n bytes4 constant private ERC1271_INVALID_SIGNATURE = 0xffffffff;\n\n /**\n * @dev Internal constructor\n */\n constructor() internal Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `AccountImplementation` contract\n * @param registry_ registry address\n */\n function initialize(\n address registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n // ERC1820\n\n function canImplementInterfaceForAddress(\n bytes32 interfaceHash,\n address addr\n )\n external\n view\n returns(bytes32)\n {\n bytes32 result;\n\n if (interfaceHash == ERC777_TOKENS_RECIPIENT_INTERFACE_HASH && addr == address(this)) {\n result = ERC1820_ACCEPT_MAGIC;\n }\n\n return result;\n }\n\n // ERC1271\n\n function isValidSignature(\n bytes32 messageHash,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), messageHash, signature)\n ? ERC1271_VALID_MESSAGE_HASH_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n function isValidSignature(\n bytes calldata message,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), message, signature)\n ? ERC1271_VALID_MESSAGE_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n // external functions (pure)\n\n // ERC721\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC721Received.selector;\n }\n\n // ERC1155\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC1155Received.selector;\n }\n\n // ERC777\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n )\n external\n pure\n {}\n}\n" + }, + "src/personal/PersonalAccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/account/AccountImplementationV1.sol\";\n\n\n/**\n * @title Personal account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\n\n /**\n * @dev Public constructor\n */\n constructor() public AccountImplementationV1() {}\n}\n" + }, + "src/common/account/mocks/AccountImplementationV1Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountImplementationV1.sol\";\n\n\n/**\n * @title Account implementation mock (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1Mock is AccountImplementationV1 {\n /**\n * @dev Public constructor\n * @param registry_ account registry address\n */\n constructor(\n address registry_\n )\n public\n AccountImplementationV1()\n {\n registry = registry_;\n }\n}\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/goerli/.pendingTransactions b/deployments/goerli/.pendingTransactions new file mode 100644 index 00000000..222a8f61 --- /dev/null +++ b/deployments/goerli/.pendingTransactions @@ -0,0 +1,17 @@ +{ + "0x5d1526546b15cc9c23dfdda9c05c66db27468bcdf75f3dbc3ce43d63670e96d8": { + "decoded": { + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "gasPrice": "10000000000", + "gasLimit": "2862866", + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "value": "0", + "nonce": 131, + "data": "0xb951433d313b5c9fec056dae66ca47abc822e0a17c3de20a5a713b9393a60a0a608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a", + "r": "0xce0e6087924683867d71e7a99475d0663d0578644fb65b14b01611cb2c46d972", + "s": "0x6f5fa4f9a361de2261fd8abd20390a1b9d5e71299a72299c07e66f6073b4905f", + "v": 45, + "chainId": 5 + } + } +} \ No newline at end of file diff --git a/deployments/goerli/GatewayV2.json b/deployments/goerli/GatewayV2.json new file mode 100644 index 00000000..07e1f842 --- /dev/null +++ b/deployments/goerli/GatewayV2.json @@ -0,0 +1,911 @@ +{ + "address": "0xBEd52610518788B931f7825301909e7616273d47", + "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" + } + ], + "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 \",\"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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 ", + "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" + } + } + }, + "transactionHash": "0x5d1526546b15cc9c23dfdda9c05c66db27468bcdf75f3dbc3ce43d63670e96d8" +} \ No newline at end of file diff --git a/deployments/goerli/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json b/deployments/goerli/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json new file mode 100644 index 00000000..fa380d29 --- /dev/null +++ b/deployments/goerli/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json @@ -0,0 +1,142 @@ +{ + "language": "Solidity", + "sources": { + "src/payments/PaymentRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./PaymentDepositAccount.sol\";\n\n\n/**\n * @title Payment registry\n *\n * @notice A registry for payment and payment channels\n *\n * @dev the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message.\n * Process will be rejected when any of senders channels will be committed.\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct Deposit {\n address account;\n mapping(address => uint256) withdrawnAmount;\n mapping(address => uint256) exitLockedUntil;\n }\n\n struct PaymentChannel {\n uint256 committedAmount;\n }\n\n struct DepositWithdrawal {\n address owner;\n address token;\n uint256 amount;\n }\n\n struct PaymentChannelCommit {\n address sender;\n address recipient;\n address token;\n bytes32 uid;\n uint256 blockNumber;\n uint256 amount;\n }\n\n uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;\n\n bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(\n \"DepositWithdrawal(address owner,address token,uint256 amount)\"\n );\n bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(\n \"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n uint256 public depositExitLockPeriod;\n\n mapping(address => Deposit) private deposits;\n mapping(bytes32 => PaymentChannel) private paymentChannels;\n\n // events\n\n /**\n * @dev Emitted when the deposit account is deployed\n * @param depositAccount deposit account address\n * @param owner owner address\n */\n event DepositAccountDeployed(\n address depositAccount,\n address owner\n );\n\n /**\n * @dev Emitted when the deposit exist is requested\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param lockedUntil deposit exist locked util time\n */\n event DepositExitRequested(\n address depositAccount,\n address owner,\n address token,\n uint256 lockedUntil\n );\n\n /**\n * @dev Emitted when the deposit exist is completed\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount deposit exist amount\n */\n event DepositExitCompleted(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the deposit exist is rejected\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n */\n event DepositExitRejected(\n address depositAccount,\n address owner,\n address token\n );\n\n /**\n * @dev Emitted when the deposit has been withdrawn\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount withdrawn amount\n */\n event DepositWithdrawn(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment channel has been committed\n * @param hash channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @param amount committed amount\n */\n event PaymentChannelCommitted(\n bytes32 hash,\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentWithdrawn(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been deposited\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentDeposited(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn and deposited (split)\n * @param channelHash channel hash\n * @param totalValue payment total value\n * @param depositValue payment deposited value\n */\n event PaymentSplit(\n bytes32 channelHash,\n uint256 totalValue,\n uint256 depositValue\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initialize `PaymentRegistry` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n * @param depositExitLockPeriod_ deposit exit lock period\n * @param guardians_ array of guardians addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_,\n uint256 depositExitLockPeriod_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n if (depositExitLockPeriod_ == 0) {\n depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;\n } else {\n depositExitLockPeriod = depositExitLockPeriod_;\n }\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Deploys deposit account\n * @param owner owner address\n */\n function deployDepositAccount(\n address owner\n )\n external\n {\n _deployDepositAccount(owner);\n }\n\n /**\n * @notice Requests deposit exit\n * @param token token address\n */\n function requestDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil == 0,\n \"PaymentRegistry: deposit exit already requested\"\n );\n\n _deployDepositAccount(owner);\n\n // solhint-disable-next-line not-rely-on-time\n lockedUntil = now.add(depositExitLockPeriod);\n\n deposits[owner].exitLockedUntil[token] = lockedUntil;\n\n emit DepositExitRequested(\n deposits[owner].account,\n owner,\n token,\n lockedUntil\n );\n }\n\n /**\n * @notice Processes deposit exit\n * @param token token address\n */\n function processDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil != 0,\n \"PaymentRegistry: deposit exit not requested\"\n );\n\n require(\n // solhint-disable-next-line not-rely-on-time\n lockedUntil <= now,\n \"PaymentRegistry: deposit exit locked\"\n );\n\n deposits[owner].exitLockedUntil[token] = 0;\n\n address depositAccount = deposits[owner].account;\n uint256 depositValue;\n\n if (token == address(0)) {\n depositValue = depositAccount.balance;\n } else {\n depositValue = ERC20Token(token).balanceOf(depositAccount);\n }\n\n _transferFromDeposit(\n depositAccount,\n owner,\n token,\n depositValue\n );\n\n emit DepositExitCompleted(\n depositAccount,\n owner,\n token,\n depositValue\n );\n }\n\n /**\n * @notice Withdraws deposit\n * @param token token address\n * @param amount amount to withdraw\n * @param guardianSignature guardian signature\n */\n function withdrawDeposit(\n address token,\n uint256 amount,\n bytes calldata guardianSignature\n )\n external\n {\n address owner = _getContextAccount();\n uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);\n\n require(\n value > 0,\n \"PaymentRegistry: invalid amount\"\n );\n\n bytes32 messageHash = _hashDepositWithdrawal(\n owner,\n token,\n amount\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n deposits[owner].withdrawnAmount[token] = amount;\n\n _verifyDepositExitOrDeployAccount(owner, token);\n\n _transferFromDeposit(\n deposits[owner].account,\n owner,\n token,\n value\n );\n\n emit DepositWithdrawn(\n deposits[owner].account,\n owner,\n token,\n amount\n );\n }\n\n /**\n * @notice Commits payment channel and withdraw payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndWithdraw(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue\n );\n\n emit PaymentWithdrawn(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel and deposit payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndDeposit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(recipient),\n token,\n paymentValue\n );\n\n emit PaymentDeposited(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel, withdraws and deposits (split) payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param depositPaymentValue amount to deposit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndSplit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n uint256 depositPaymentValue,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferSplitFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue,\n depositPaymentValue\n );\n\n emit PaymentSplit(hash, paymentValue, depositPaymentValue);\n }\n\n // external functions (views)\n\n /**\n * @notice Computes deposit account address\n * @param owner owner address\n * @return deposit account address\n */\n function computeDepositAccountAddress(\n address owner\n )\n external\n view\n returns (address)\n {\n return _computeDepositAccountAddress(owner);\n }\n\n /**\n * @notice Checks if deposit account is deployed\n * @param owner owner address\n * @return true when deposit account is deployed\n */\n function isDepositAccountDeployed(\n address owner\n )\n external\n view\n returns (bool)\n {\n return deposits[owner].account != address(0);\n }\n\n /**\n * @notice Gets deposit exit locked until time\n * @param owner owner address\n * @param token token address\n * @return locked until time\n */\n function getDepositExitLockedUntil(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].exitLockedUntil[token];\n }\n\n /**\n * @notice Gets deposit withdrawn amount\n * @param owner owner address\n * @param token token address\n * @return withdrawn amount\n */\n function getDepositWithdrawnAmount(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].withdrawnAmount[token];\n }\n\n /**\n * @notice Gets payment channel committed amount\n * @param hash payment channel hash\n * @return committed amount\n */\n function getPaymentChannelCommittedAmount(\n bytes32 hash\n )\n external\n view\n returns (uint256)\n {\n return paymentChannels[hash].committedAmount;\n }\n\n // external functions (pure)\n\n /**\n * @notice Computes payment channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @return hash\n */\n function computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n external\n pure\n returns (bytes32)\n {\n return _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DepositWithdrawal` message payload\n * @param depositWithdrawal struct\n * @return hash\n */\n function hashDepositWithdrawal(\n DepositWithdrawal memory depositWithdrawal\n )\n public\n view\n returns (bytes32)\n {\n return _hashDepositWithdrawal(\n depositWithdrawal.owner,\n depositWithdrawal.token,\n depositWithdrawal.amount\n );\n }\n\n /**\n * @notice Hashes `PaymentChannelCommit` message payload\n * @param paymentChannelCommit struct\n * @return hash\n */\n function hashPaymentChannelCommit(\n PaymentChannelCommit memory paymentChannelCommit\n )\n public\n view\n returns (bytes32)\n {\n return _hashPaymentChannelCommit(\n paymentChannelCommit.sender,\n paymentChannelCommit.recipient,\n paymentChannelCommit.token,\n paymentChannelCommit.uid,\n paymentChannelCommit.blockNumber,\n paymentChannelCommit.amount\n );\n }\n\n // private functions\n\n function _deployDepositAccount(\n address owner\n )\n private\n {\n if (deposits[owner].account == address(0)) {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());\n\n emit DepositAccountDeployed(\n deposits[owner].account,\n owner\n );\n }\n }\n\n function _verifyDepositExitOrDeployAccount(\n address owner,\n address token\n )\n private\n {\n if (deposits[owner].exitLockedUntil[token] > 0) {\n deposits[owner].exitLockedUntil[token] = 0;\n\n emit DepositExitRejected(\n deposits[owner].account,\n owner,\n token\n );\n } else {\n _deployDepositAccount(owner);\n }\n }\n\n function _commitPaymentChannel(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes memory senderSignature,\n bytes memory guardianSignature\n )\n private\n returns (bytes32 hash, address depositAccount, uint256 paymentValue)\n {\n bytes32 messageHash = _hashPaymentChannelCommit(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n );\n\n if (senderSignature.length == 0) {\n require(\n externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),\n \"PaymentRegistry: invalid guardian signature\"\n );\n } else {\n address signer = messageHash.recoverAddress(senderSignature);\n\n if (sender != signer) {\n require(\n personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||\n externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),\n \"PaymentRegistry: invalid sender signature\"\n );\n }\n }\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n hash = _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n\n /// @dev calc payment value\n paymentValue = amount.sub(paymentChannels[hash].committedAmount);\n\n require(\n paymentValue != 0,\n \"PaymentRegistry: invalid payment value\"\n );\n\n paymentChannels[hash].committedAmount = amount;\n\n _verifyDepositExitOrDeployAccount(sender, token);\n\n depositAccount = deposits[sender].account;\n\n emit PaymentChannelCommitted(\n hash,\n sender,\n recipient,\n token,\n uid,\n amount\n );\n\n return (hash, depositAccount, paymentValue);\n }\n\n function _transferFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 value\n )\n private\n {\n if (token == address(0)) {\n PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n to,\n value,\n new bytes(0)\n );\n } else {\n bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n token,\n 0,\n abi.encodeWithSelector(\n ERC20Token(token).transfer.selector,\n to,\n value\n )\n );\n\n if (response.length > 0) {\n require(\n abi.decode(response, (bool)),\n \"PaymentRegistry: ERC20Token transfer reverted\"\n );\n }\n }\n }\n\n function _transferSplitFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 paymentValue,\n uint256 depositValue\n )\n private\n {\n require(\n depositValue > 0,\n \"PaymentRegistry: invalid deposit value\"\n );\n\n uint256 withdrawValue = paymentValue.sub(depositValue);\n\n require(\n withdrawValue > 0,\n \"PaymentRegistry: invalid withdraw value\"\n );\n\n _transferFromDeposit(\n depositAccount,\n to,\n token,\n withdrawValue\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(to),\n token,\n depositValue\n );\n }\n\n // private functions (views)\n\n function _computeDepositAccountAddress(\n address owner\n )\n private\n view\n returns (address)\n {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n bytes memory creationCode = type(PaymentDepositAccount).creationCode;\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 function _hashDepositWithdrawal(\n address owner,\n address token,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(\n owner,\n token,\n amount\n ));\n }\n\n function _hashPaymentChannelCommit(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n ));\n }\n\n // private functions (pure)\n\n function _computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n private\n pure\n returns (bytes32)\n {\n return keccak256(\n abi.encodePacked(\n sender,\n recipient,\n token,\n uid\n )\n );\n }\n}\n" + }, + "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ław Głogowski \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" + }, + "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" + }, + "src/common/libs/SafeMathLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n" + }, + "src/common/lifecycle/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski \n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n" + }, + "src/common/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ław Głogowski \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" + }, + "src/common/token/ERC20Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n" + }, + "src/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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "src/gateway/GatewayRecipient.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n" + }, + "src/payments/PaymentDepositAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/access/Controlled.sol\";\n\n\n/**\n * @title Payment deposit account\n *\n * @dev Simple account contract with only one method - `executeTransaction`\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentDepositAccount is Controlled {\n /**\n * @dev Public constructor\n */\n constructor() public payable Controlled() {}\n\n /**\n * @notice Allow receives\n */\n receive()\n external\n payable\n {\n //\n }\n\n // external functions\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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \n */\ncontract AccountBase {\n address public registry;\n}\n" + }, + "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" + }, + "src/common/libs/BytesLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski \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" + }, + "src/tokens/WrappedWeiToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski \n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n" + }, + "src/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 \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" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.12;\r\npragma experimental ABIEncoderV2;\r\n\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/**\r\n * @title Gateway\r\n *\r\n * @notice GSN replacement\r\n *\r\n * @author Stanisław Głogowski \r\n */\r\ncontract Gateway is Initializable, SignatureValidator {\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\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 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 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 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 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 // 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}" + }, + "src/ens/ENSController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./resolvers/ENSPubKeyResolver.sol\";\nimport \"./resolvers/ENSTextResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n\n/**\n * @title ENS controller\n *\n * @notice ENS subnode registrar\n *\n * @dev The process of adding root node consists of 3 steps:\n * 1. `submitNode` - should be called from ENS node owner,\n * 2. Change ENS node owner in ENS registry to ENS controller,\n * 3. `verifyNode` - should be called from previous ENS node owner,\n *\n * To register sub node, `msg.sender` need to send valid signature from one of guardian key.\n * Once registration is complete `msg.sender` becoming both node owner and `addr` record value.\n *\n * After registration sub node cannot be replaced.\n *\n * @author Stanisław Głogowski \n */\ncontract ENSController is Guarded, Initializable, SignatureValidator, GatewayRecipient, ENSAddressResolver, ENSNameResolver, ENSPubKeyResolver, ENSTextResolver {\n struct SubNodeRegistration {\n address account;\n bytes32 node;\n bytes32 label;\n }\n\n bytes4 private constant INTERFACE_META_ID = bytes4(keccak256(abi.encodePacked(\"supportsInterface(bytes4)\")));\n\n bytes32 private constant HASH_PREFIX_SUB_NODE_REGISTRATION = keccak256(\n \"SubNodeRegistration(address account,bytes32 node,bytes32 label)\"\n );\n\n ENSRegistry public registry;\n\n mapping(bytes32 => address) public nodeOwners;\n\n // events\n\n /**\n * @dev Emitted when new node is submitted\n * @param node node name hash\n * @param owner owner address\n */\n event NodeSubmitted(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when the existing owner is verified\n * @param node node name hash\n */\n event NodeVerified(\n bytes32 node\n );\n\n /**\n * @dev Emitted when new node is released\n * @param node node name hash\n * @param owner owner address\n */\n event NodeReleased(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when ENS registry address is changed\n * @param registry registry address\n */\n event RegistryChanged(\n address registry\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Guarded() Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSController` contract\n * @param registry_ ENS registry address\n * @param gateway_ gateway address\n */\n function initialize(\n ENSRegistry registry_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n registry = registry_;\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Sets registry\n * @param registry_ registry address\n */\n function setRegistry(\n ENSRegistry registry_\n )\n external\n onlyGuardian\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n require(\n registry_ != registry,\n \"ENSController: registry already set\"\n );\n\n registry = registry_;\n\n emit RegistryChanged(\n address(registry)\n );\n }\n\n /**\n * @notice Submits node\n * @dev Should be called from the current ENS node owner\n * @param node node name hash\n */\n function submitNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == address(0),\n \"ENSController: node already submitted\"\n );\n\n require(\n registry.owner(node) == owner,\n \"ENSController: invalid ens node owner\"\n );\n\n nodeOwners[node] = owner;\n\n emit NodeSubmitted(node, owner);\n }\n\n /**\n * @notice Verifies node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function verifyNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n require(\n registry.owner(node) == address(this),\n \"ENSController: invalid ens node owner\"\n );\n\n _setAddr(node, address(this));\n\n registry.setResolver(node, address(this));\n\n emit NodeVerified(node);\n }\n\n /**\n * @notice Releases node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function releaseNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(this),\n \"ENSController: node doesn't exist\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n registry.setOwner(node, owner);\n\n delete nodeOwners[node];\n\n emit NodeReleased(node, owner);\n }\n\n /**\n * @notice Sync address\n * @param node node name hash\n */\n function syncAddr(\n bytes32 node\n )\n external\n {\n address account = _getContextAccount();\n\n require(\n account == registry.owner(node),\n \"ENSController: caller is not the node owner\"\n );\n\n require(\n registry.resolver(node) == address(this),\n \"ENSController: invalid node resolver\"\n );\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already in sync\"\n );\n\n _setAddr(node, account);\n }\n\n /**\n * @notice Registers sub node\n * @param node node name hash\n * @param label label hash\n * @param guardianSignature guardian signature\n */\n function registerSubNode(\n bytes32 node,\n bytes32 label,\n bytes calldata guardianSignature\n )\n external\n {\n address account = _getContextAccount();\n\n bytes32 messageHash = _hashSubNodeRegistration(\n account,\n node,\n label\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"ENSController: invalid guardian signature\"\n );\n\n bytes32 subNode = keccak256(\n abi.encodePacked(\n node,\n label\n )\n );\n\n require(\n _addr(node) == address(this),\n \"ENSController: invalid node\"\n );\n\n require(\n _addr(subNode) == address(0),\n \"ENSController: label already taken\"\n );\n\n registry.setSubnodeRecord(node, label, address(this), address(this), 0);\n registry.setOwner(subNode, account);\n\n _setAddr(subNode, account);\n }\n\n // external functions (pure)\n function supportsInterface(\n bytes4 interfaceID\n )\n external\n pure\n returns(bool)\n {\n return interfaceID == INTERFACE_META_ID ||\n interfaceID == INTERFACE_ADDR_ID ||\n interfaceID == INTERFACE_ADDRESS_ID ||\n interfaceID == INTERFACE_NAME_ID ||\n interfaceID == INTERFACE_PUB_KEY_ID ||\n interfaceID == INTERFACE_TEXT_ID;\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `SubNodeRegistration` message payload\n * @param subNodeRegistration struct\n * @return hash\n */\n function hashSubNodeRegistration(\n SubNodeRegistration memory subNodeRegistration\n )\n public\n view\n returns (bytes32)\n {\n return _hashSubNodeRegistration(\n subNodeRegistration.account,\n subNodeRegistration.node,\n subNodeRegistration.label\n );\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n override\n view\n returns (bool)\n {\n return registry.owner(node) == _getContextAccount();\n }\n\n // private functions (views)\n\n function _hashSubNodeRegistration(\n address account,\n bytes32 node,\n bytes32 label\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_SUB_NODE_REGISTRATION, abi.encodePacked(\n account,\n node,\n label\n ));\n }\n}\n" + }, + "src/ens/resolvers/ENSAddressResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract address resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/AddrResolver.sol\n */\nabstract contract ENSAddressResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_ADDR_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32)\")));\n bytes4 internal constant INTERFACE_ADDRESS_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32,uint)\")));\n\n uint internal constant COIN_TYPE_ETH = 60;\n\n mapping(bytes32 => mapping(uint => bytes)) internal resolverAddresses;\n\n // events\n\n event AddrChanged(\n bytes32 indexed node,\n address addr\n );\n\n event AddressChanged(\n bytes32 indexed node,\n uint coinType,\n bytes newAddress\n );\n\n // external functions\n\n function setAddr(\n bytes32 node,\n address addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, addr_);\n }\n\n function setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, coinType, addr_);\n }\n\n // external functions (views)\n\n function addr(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return _addr(node);\n }\n\n function addr(\n bytes32 node,\n uint coinType\n )\n external\n view\n returns (bytes memory)\n {\n return resolverAddresses[node][coinType];\n }\n\n // internal functions\n\n function _setAddr(\n bytes32 node,\n address addr_\n )\n internal\n {\n _setAddr(node, COIN_TYPE_ETH, _addressToBytes(addr_));\n }\n\n function _setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n internal\n {\n emit AddressChanged(node, coinType, addr_);\n\n if(coinType == COIN_TYPE_ETH) {\n emit AddrChanged(node, _bytesToAddress(addr_));\n }\n\n resolverAddresses[node][coinType] = addr_;\n }\n\n // internal functions (views)\n\n function _addr(\n bytes32 node\n )\n internal\n view\n returns (address)\n {\n address result;\n\n bytes memory addr_ = resolverAddresses[node][COIN_TYPE_ETH];\n\n if (addr_.length > 0) {\n result = _bytesToAddress(addr_);\n }\n\n return result;\n }\n\n // private function (pure)\n\n function _bytesToAddress(\n bytes memory data\n )\n private\n pure\n returns(address payable)\n {\n address payable result;\n\n require(data.length == 20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 32)), exp(256, 12))\n }\n\n return result;\n }\n\n function _addressToBytes(\n address addr_\n )\n private\n pure\n returns(bytes memory)\n {\n bytes memory result = new bytes(20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(add(result, 32), mul(addr_, exp(256, 12)))\n }\n\n return result;\n }\n}\n" + }, + "src/ens/resolvers/ENSNameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract name resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/NameResolver.sol\n */\nabstract contract ENSNameResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_NAME_ID = bytes4(keccak256(abi.encodePacked(\"name(bytes32)\")));\n\n mapping(bytes32 => string) internal resolverNames;\n\n // events\n\n event NameChanged(\n bytes32 indexed node,\n string name\n );\n\n // external functions\n\n function setName(\n bytes32 node,\n string calldata name\n )\n external\n onlyNodeOwner(node)\n {\n resolverNames[node] = name;\n\n emit NameChanged(node, name);\n }\n\n // external functions (views)\n\n function name(\n bytes32 node\n )\n external\n view\n returns (string memory)\n {\n return resolverNames[node];\n }\n}\n" + }, + "src/ens/resolvers/ENSPubKeyResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract pub key resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/PubkeyResolver.sol\n */\nabstract contract ENSPubKeyResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_PUB_KEY_ID = bytes4(keccak256(abi.encodePacked(\"pubkey(bytes32)\")));\n\n struct PubKey {\n bytes32 x;\n bytes32 y;\n }\n\n mapping(bytes32 => PubKey) internal resolverPubKeys;\n\n // events\n\n event PubkeyChanged(\n bytes32 indexed node,\n bytes32 x,\n bytes32 y\n );\n\n // external functions (views)\n\n function setPubkey(\n bytes32 node,\n bytes32 x,\n bytes32 y\n )\n external\n onlyNodeOwner(node)\n {\n resolverPubKeys[node] = PubKey(x, y);\n\n emit PubkeyChanged(node, x, y);\n }\n\n // external functions (views)\n\n function pubkey(\n bytes32 node\n )\n external\n view\n returns (bytes32 x, bytes32 y)\n {\n return (resolverPubKeys[node].x, resolverPubKeys[node].y);\n }\n}\n" + }, + "src/ens/resolvers/ENSTextResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract text resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/TextResolver.sol\n */\nabstract contract ENSTextResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_TEXT_ID = bytes4(keccak256(abi.encodePacked(\"text(bytes32,string)\")));\n\n mapping(bytes32 => mapping(string => string)) internal resolverTexts;\n\n // events\n\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key\n );\n\n // external functions (views)\n\n function setText(\n bytes32 node,\n string calldata key,\n string calldata value\n )\n external\n onlyNodeOwner(node)\n {\n resolverTexts[node][key] = value;\n\n emit TextChanged(node, key, key);\n }\n\n // external functions (views)\n\n function text(\n bytes32 node,\n string calldata key\n )\n external\n view\n returns (string memory)\n {\n return resolverTexts[node][key];\n }\n}\n" + }, + "src/ens/ENSRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS registry\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\n */\ncontract ENSRegistry {\n struct Record {\n address owner;\n address resolver;\n uint64 ttl;\n }\n\n mapping (bytes32 => Record) private records;\n mapping (address => mapping(address => bool)) private operators;\n\n // events\n\n event NewOwner(\n bytes32 indexed node,\n bytes32 indexed label,\n address owner\n );\n\n event Transfer(\n bytes32 indexed node,\n address owner\n );\n\n event NewResolver(\n bytes32 indexed node,\n address resolver\n );\n\n event NewTTL(\n bytes32 indexed node,\n uint64 ttl\n );\n\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n // modifiers\n\n modifier authorised(\n bytes32 node\n )\n {\n address owner = records[node].owner;\n\n require(\n owner == msg.sender || operators[owner][msg.sender],\n \"ENSRegistry: reverted by authorised modifier\"\n );\n\n _;\n }\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n {\n // solhint-disable-next-line avoid-tx-origin\n records[0x0].owner = tx.origin;\n }\n\n // external functions\n\n function setRecord(\n bytes32 node,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n setOwner(node, owner_);\n\n _setResolverAndTTL(node, resolver_, ttl_);\n }\n\n function setTTL(\n bytes32 node,\n uint64 ttl_\n )\n external\n authorised(node)\n {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n bytes32 subNode = setSubnodeOwner(node, label, owner_);\n\n _setResolverAndTTL(subNode, resolver_, ttl_);\n }\n\n function setApprovalForAll(\n address operator,\n bool approved\n )\n external\n {\n operators[msg.sender][operator] = approved;\n\n emit ApprovalForAll(\n msg.sender,\n operator,\n approved\n );\n }\n\n // external functions (views)\n\n function owner(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n address addr = records[node].owner;\n\n if (addr == address(this)) {\n return address(0x0);\n }\n\n return addr;\n }\n\n function resolver(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return records[node].resolver;\n }\n\n function ttl(\n bytes32 node\n )\n external\n view\n returns (uint64)\n {\n return records[node].ttl;\n }\n\n function recordExists(\n bytes32 node\n )\n external\n view\n returns (bool)\n {\n return records[node].owner != address(0x0);\n }\n\n function isApprovedForAll(\n address owner_,\n address operator\n )\n external\n view\n returns (bool)\n {\n return operators[owner_][operator];\n }\n\n // public functions\n\n function setOwner(\n bytes32 node,\n address owner_\n )\n public\n authorised(node)\n {\n records[node].owner = owner_;\n\n emit Transfer(node, owner_);\n }\n\n function setResolver(\n bytes32 node,\n address resolver_\n )\n public\n authorised(node)\n {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner_\n )\n public\n authorised(node)\n returns(bytes32)\n {\n bytes32 subNode = keccak256(abi.encodePacked(node, label));\n\n records[subNode].owner = owner_;\n\n emit NewOwner(node, label, owner_);\n\n return subNode;\n }\n\n // private functions\n\n function _setResolverAndTTL(\n bytes32 node,\n address resolver_,\n uint64 ttl_\n )\n private\n {\n if (resolver_ != records[node].resolver) {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n if (ttl_ != records[node].ttl) {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n }\n}\n" + }, + "src/ens/resolvers/ENSAbstractResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS abstract resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/ResolverBase.sol\n */\nabstract contract ENSAbstractResolver {\n // modifiers\n\n modifier onlyNodeOwner(bytes32 node)\n {\n require(\n _isNodeOwner(node),\n \"ENSAbstractResolver: reverted by onlyNodeOwner modifier\"\n );\n\n _;\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n virtual\n view\n returns (bool);\n}\n" + }, + "src/ens/ENSReverseRegistrar.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/AddressLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS reverse registrar\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\n */\ncontract ENSReverseRegistrar is Initializable {\n using AddressLib for address;\n\n // namehash('addr.reverse')\n bytes32 public constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n ENSRegistry public registry;\n ENSNameResolver public resolver;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSReverseRegistrar` contract\n * @param registry_ ENS registry address\n * @param resolver_ ENS name resolver address\n */\n function initialize(\n ENSRegistry registry_,\n ENSNameResolver resolver_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n resolver = resolver_;\n }\n\n // external functions\n\n function claim(\n address owner\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, address(0));\n }\n\n function claimWithResolver(\n address owner,\n address resolver_\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, resolver_);\n }\n\n function setName(\n string memory name\n )\n public\n returns (bytes32)\n {\n bytes32 node = _claimWithResolver(address(this), address(resolver));\n\n resolver.setName(node, name);\n\n return node;\n }\n\n // external functions (pure)\n\n function node(\n address addr_\n )\n external\n pure\n returns (bytes32)\n {\n return keccak256(abi.encodePacked(ADDR_REVERSE_NODE, addr_.toSha3Hash()));\n }\n\n // private functions\n\n function _claimWithResolver(\n address owner,\n address resolver_\n )\n private\n returns (bytes32)\n {\n bytes32 label = address(msg.sender).toSha3Hash();\n bytes32 node_ = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n address currentOwner = registry.owner(node_);\n\n if (resolver_ != address(0x0) && resolver_ != registry.resolver(node_)) {\n if (currentOwner != address(this)) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this));\n currentOwner = address(this);\n }\n\n registry.setResolver(node_, resolver_);\n }\n\n // Update the owner if required\n if (currentOwner != owner) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);\n }\n\n return node_;\n }\n}\n" + }, + "src/common/libs/AddressLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Address library\n */\nlibrary AddressLib {\n /**\n * @notice Converts address into sha3 hash\n * @param self address\n * @return sha3 hash\n */\n function toSha3Hash(\n address self\n )\n internal\n pure\n returns (bytes32)\n {\n bytes32 result;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000\n\n for { let i := 40 } gt(i, 0) { } {\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n }\n\n result := keccak256(0, 40)\n }\n\n return result;\n }\n}\n" + }, + "src/ens/ENSHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS helper\n *\n * @author Stanisław Głogowski \n */\ncontract ENSHelper is Initializable {\n ENSRegistry public registry;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSLookupHelper` contract\n * @param registry_ ENS registry address\n */\n function initialize(\n ENSRegistry registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n /**\n * @notice Gets nodes addresses\n * @param nodes array of nodes\n * @return nodes addresses\n */\n function getAddresses(\n bytes32[] memory nodes\n )\n external\n view\n returns (address[] memory)\n {\n uint nodesLen = nodes.length;\n address[] memory result = new address[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getAddress(nodes[i]);\n }\n\n return result;\n }\n\n /**\n * @notice Gets nodes names\n * @param nodes array of nodes\n * @return nodes names\n */\n function getNames(\n bytes32[] memory nodes\n )\n external\n view\n returns (string[] memory)\n {\n uint nodesLen = nodes.length;\n string[] memory result = new string[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getName(nodes[i]);\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getAddress(\n bytes32 node\n )\n private\n view\n returns (address)\n {\n address result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSAddressResolver(resolver).addr(node) returns (address addr) {\n result = addr;\n } catch {\n //\n }\n }\n\n return result;\n }\n\n function _getName(\n bytes32 node\n )\n private\n view\n returns (string memory)\n {\n string memory result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSNameResolver(resolver).name(node) returns (string memory name) {\n result = name;\n } catch {\n //\n }\n }\n\n return result;\n }\n}\n" + }, + "src/common/account/AccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../lifecycle/Initializable.sol\";\nimport \"./AccountBase.sol\";\nimport \"./AccountRegistry.sol\";\n\n\n/**\n * @title Account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1 is Initializable, AccountBase {\n bytes32 constant private ERC777_TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(abi.encodePacked(\"ERC777TokensRecipient\"));\n bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n bytes4 constant private ERC1271_VALID_MESSAGE_HASH_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes32,bytes)\")));\n bytes4 constant private ERC1271_VALID_MESSAGE_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes,bytes)\")));\n bytes4 constant private ERC1271_INVALID_SIGNATURE = 0xffffffff;\n\n /**\n * @dev Internal constructor\n */\n constructor() internal Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `AccountImplementation` contract\n * @param registry_ registry address\n */\n function initialize(\n address registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n // ERC1820\n\n function canImplementInterfaceForAddress(\n bytes32 interfaceHash,\n address addr\n )\n external\n view\n returns(bytes32)\n {\n bytes32 result;\n\n if (interfaceHash == ERC777_TOKENS_RECIPIENT_INTERFACE_HASH && addr == address(this)) {\n result = ERC1820_ACCEPT_MAGIC;\n }\n\n return result;\n }\n\n // ERC1271\n\n function isValidSignature(\n bytes32 messageHash,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), messageHash, signature)\n ? ERC1271_VALID_MESSAGE_HASH_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n function isValidSignature(\n bytes calldata message,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), message, signature)\n ? ERC1271_VALID_MESSAGE_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n // external functions (pure)\n\n // ERC721\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC721Received.selector;\n }\n\n // ERC1155\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC1155Received.selector;\n }\n\n // ERC777\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n )\n external\n pure\n {}\n}\n" + }, + "src/personal/PersonalAccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/account/AccountImplementationV1.sol\";\n\n\n/**\n * @title Personal account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\n\n /**\n * @dev Public constructor\n */\n constructor() public AccountImplementationV1() {}\n}\n" + }, + "src/common/account/mocks/AccountImplementationV1Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountImplementationV1.sol\";\n\n\n/**\n * @title Account implementation mock (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1Mock is AccountImplementationV1 {\n /**\n * @dev Public constructor\n * @param registry_ account registry address\n */\n constructor(\n address registry_\n )\n public\n AccountImplementationV1()\n {\n registry = registry_;\n }\n}\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/mumbai/.pendingTransactions b/deployments/mumbai/.pendingTransactions new file mode 100644 index 00000000..a4fd2bb9 --- /dev/null +++ b/deployments/mumbai/.pendingTransactions @@ -0,0 +1,17 @@ +{ + "0x7cde877042ec6ecd354253675d33900153c4819422956b07c0ccbbbd3817a3a2": { + "decoded": { + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "gasPrice": "70000000000", + "gasLimit": "2862866", + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "value": "0", + "nonce": 45, + "data": "0xb951433d313b5c9fec056dae66ca47abc822e0a17c3de20a5a713b9393a60a0a608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a", + "r": "0x8e22faae9b665cebddbc681bae9f42af5113aad2829b0f2adc3febf918de6846", + "s": "0x5073378f5b664aede8cd1a05a7b9b76585a5fbd00294decb73eafca46450ccf7", + "v": 160038, + "chainId": 80001 + } + } +} \ No newline at end of file diff --git a/deployments/mumbai/GatewayV2.json b/deployments/mumbai/GatewayV2.json new file mode 100644 index 00000000..13ba41b8 --- /dev/null +++ b/deployments/mumbai/GatewayV2.json @@ -0,0 +1,910 @@ +{ + "address": "0xBEd52610518788B931f7825301909e7616273d47", + "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" + } + ], + "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 \",\"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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 ", + "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" + } + } + } +} \ No newline at end of file diff --git a/deployments/mumbai/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json b/deployments/mumbai/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json new file mode 100644 index 00000000..fa380d29 --- /dev/null +++ b/deployments/mumbai/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json @@ -0,0 +1,142 @@ +{ + "language": "Solidity", + "sources": { + "src/payments/PaymentRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./PaymentDepositAccount.sol\";\n\n\n/**\n * @title Payment registry\n *\n * @notice A registry for payment and payment channels\n *\n * @dev the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message.\n * Process will be rejected when any of senders channels will be committed.\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct Deposit {\n address account;\n mapping(address => uint256) withdrawnAmount;\n mapping(address => uint256) exitLockedUntil;\n }\n\n struct PaymentChannel {\n uint256 committedAmount;\n }\n\n struct DepositWithdrawal {\n address owner;\n address token;\n uint256 amount;\n }\n\n struct PaymentChannelCommit {\n address sender;\n address recipient;\n address token;\n bytes32 uid;\n uint256 blockNumber;\n uint256 amount;\n }\n\n uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;\n\n bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(\n \"DepositWithdrawal(address owner,address token,uint256 amount)\"\n );\n bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(\n \"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n uint256 public depositExitLockPeriod;\n\n mapping(address => Deposit) private deposits;\n mapping(bytes32 => PaymentChannel) private paymentChannels;\n\n // events\n\n /**\n * @dev Emitted when the deposit account is deployed\n * @param depositAccount deposit account address\n * @param owner owner address\n */\n event DepositAccountDeployed(\n address depositAccount,\n address owner\n );\n\n /**\n * @dev Emitted when the deposit exist is requested\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param lockedUntil deposit exist locked util time\n */\n event DepositExitRequested(\n address depositAccount,\n address owner,\n address token,\n uint256 lockedUntil\n );\n\n /**\n * @dev Emitted when the deposit exist is completed\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount deposit exist amount\n */\n event DepositExitCompleted(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the deposit exist is rejected\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n */\n event DepositExitRejected(\n address depositAccount,\n address owner,\n address token\n );\n\n /**\n * @dev Emitted when the deposit has been withdrawn\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount withdrawn amount\n */\n event DepositWithdrawn(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment channel has been committed\n * @param hash channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @param amount committed amount\n */\n event PaymentChannelCommitted(\n bytes32 hash,\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentWithdrawn(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been deposited\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentDeposited(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn and deposited (split)\n * @param channelHash channel hash\n * @param totalValue payment total value\n * @param depositValue payment deposited value\n */\n event PaymentSplit(\n bytes32 channelHash,\n uint256 totalValue,\n uint256 depositValue\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initialize `PaymentRegistry` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n * @param depositExitLockPeriod_ deposit exit lock period\n * @param guardians_ array of guardians addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_,\n uint256 depositExitLockPeriod_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n if (depositExitLockPeriod_ == 0) {\n depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;\n } else {\n depositExitLockPeriod = depositExitLockPeriod_;\n }\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Deploys deposit account\n * @param owner owner address\n */\n function deployDepositAccount(\n address owner\n )\n external\n {\n _deployDepositAccount(owner);\n }\n\n /**\n * @notice Requests deposit exit\n * @param token token address\n */\n function requestDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil == 0,\n \"PaymentRegistry: deposit exit already requested\"\n );\n\n _deployDepositAccount(owner);\n\n // solhint-disable-next-line not-rely-on-time\n lockedUntil = now.add(depositExitLockPeriod);\n\n deposits[owner].exitLockedUntil[token] = lockedUntil;\n\n emit DepositExitRequested(\n deposits[owner].account,\n owner,\n token,\n lockedUntil\n );\n }\n\n /**\n * @notice Processes deposit exit\n * @param token token address\n */\n function processDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil != 0,\n \"PaymentRegistry: deposit exit not requested\"\n );\n\n require(\n // solhint-disable-next-line not-rely-on-time\n lockedUntil <= now,\n \"PaymentRegistry: deposit exit locked\"\n );\n\n deposits[owner].exitLockedUntil[token] = 0;\n\n address depositAccount = deposits[owner].account;\n uint256 depositValue;\n\n if (token == address(0)) {\n depositValue = depositAccount.balance;\n } else {\n depositValue = ERC20Token(token).balanceOf(depositAccount);\n }\n\n _transferFromDeposit(\n depositAccount,\n owner,\n token,\n depositValue\n );\n\n emit DepositExitCompleted(\n depositAccount,\n owner,\n token,\n depositValue\n );\n }\n\n /**\n * @notice Withdraws deposit\n * @param token token address\n * @param amount amount to withdraw\n * @param guardianSignature guardian signature\n */\n function withdrawDeposit(\n address token,\n uint256 amount,\n bytes calldata guardianSignature\n )\n external\n {\n address owner = _getContextAccount();\n uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);\n\n require(\n value > 0,\n \"PaymentRegistry: invalid amount\"\n );\n\n bytes32 messageHash = _hashDepositWithdrawal(\n owner,\n token,\n amount\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n deposits[owner].withdrawnAmount[token] = amount;\n\n _verifyDepositExitOrDeployAccount(owner, token);\n\n _transferFromDeposit(\n deposits[owner].account,\n owner,\n token,\n value\n );\n\n emit DepositWithdrawn(\n deposits[owner].account,\n owner,\n token,\n amount\n );\n }\n\n /**\n * @notice Commits payment channel and withdraw payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndWithdraw(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue\n );\n\n emit PaymentWithdrawn(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel and deposit payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndDeposit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(recipient),\n token,\n paymentValue\n );\n\n emit PaymentDeposited(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel, withdraws and deposits (split) payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param depositPaymentValue amount to deposit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndSplit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n uint256 depositPaymentValue,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferSplitFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue,\n depositPaymentValue\n );\n\n emit PaymentSplit(hash, paymentValue, depositPaymentValue);\n }\n\n // external functions (views)\n\n /**\n * @notice Computes deposit account address\n * @param owner owner address\n * @return deposit account address\n */\n function computeDepositAccountAddress(\n address owner\n )\n external\n view\n returns (address)\n {\n return _computeDepositAccountAddress(owner);\n }\n\n /**\n * @notice Checks if deposit account is deployed\n * @param owner owner address\n * @return true when deposit account is deployed\n */\n function isDepositAccountDeployed(\n address owner\n )\n external\n view\n returns (bool)\n {\n return deposits[owner].account != address(0);\n }\n\n /**\n * @notice Gets deposit exit locked until time\n * @param owner owner address\n * @param token token address\n * @return locked until time\n */\n function getDepositExitLockedUntil(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].exitLockedUntil[token];\n }\n\n /**\n * @notice Gets deposit withdrawn amount\n * @param owner owner address\n * @param token token address\n * @return withdrawn amount\n */\n function getDepositWithdrawnAmount(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].withdrawnAmount[token];\n }\n\n /**\n * @notice Gets payment channel committed amount\n * @param hash payment channel hash\n * @return committed amount\n */\n function getPaymentChannelCommittedAmount(\n bytes32 hash\n )\n external\n view\n returns (uint256)\n {\n return paymentChannels[hash].committedAmount;\n }\n\n // external functions (pure)\n\n /**\n * @notice Computes payment channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @return hash\n */\n function computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n external\n pure\n returns (bytes32)\n {\n return _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DepositWithdrawal` message payload\n * @param depositWithdrawal struct\n * @return hash\n */\n function hashDepositWithdrawal(\n DepositWithdrawal memory depositWithdrawal\n )\n public\n view\n returns (bytes32)\n {\n return _hashDepositWithdrawal(\n depositWithdrawal.owner,\n depositWithdrawal.token,\n depositWithdrawal.amount\n );\n }\n\n /**\n * @notice Hashes `PaymentChannelCommit` message payload\n * @param paymentChannelCommit struct\n * @return hash\n */\n function hashPaymentChannelCommit(\n PaymentChannelCommit memory paymentChannelCommit\n )\n public\n view\n returns (bytes32)\n {\n return _hashPaymentChannelCommit(\n paymentChannelCommit.sender,\n paymentChannelCommit.recipient,\n paymentChannelCommit.token,\n paymentChannelCommit.uid,\n paymentChannelCommit.blockNumber,\n paymentChannelCommit.amount\n );\n }\n\n // private functions\n\n function _deployDepositAccount(\n address owner\n )\n private\n {\n if (deposits[owner].account == address(0)) {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());\n\n emit DepositAccountDeployed(\n deposits[owner].account,\n owner\n );\n }\n }\n\n function _verifyDepositExitOrDeployAccount(\n address owner,\n address token\n )\n private\n {\n if (deposits[owner].exitLockedUntil[token] > 0) {\n deposits[owner].exitLockedUntil[token] = 0;\n\n emit DepositExitRejected(\n deposits[owner].account,\n owner,\n token\n );\n } else {\n _deployDepositAccount(owner);\n }\n }\n\n function _commitPaymentChannel(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes memory senderSignature,\n bytes memory guardianSignature\n )\n private\n returns (bytes32 hash, address depositAccount, uint256 paymentValue)\n {\n bytes32 messageHash = _hashPaymentChannelCommit(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n );\n\n if (senderSignature.length == 0) {\n require(\n externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),\n \"PaymentRegistry: invalid guardian signature\"\n );\n } else {\n address signer = messageHash.recoverAddress(senderSignature);\n\n if (sender != signer) {\n require(\n personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||\n externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),\n \"PaymentRegistry: invalid sender signature\"\n );\n }\n }\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n hash = _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n\n /// @dev calc payment value\n paymentValue = amount.sub(paymentChannels[hash].committedAmount);\n\n require(\n paymentValue != 0,\n \"PaymentRegistry: invalid payment value\"\n );\n\n paymentChannels[hash].committedAmount = amount;\n\n _verifyDepositExitOrDeployAccount(sender, token);\n\n depositAccount = deposits[sender].account;\n\n emit PaymentChannelCommitted(\n hash,\n sender,\n recipient,\n token,\n uid,\n amount\n );\n\n return (hash, depositAccount, paymentValue);\n }\n\n function _transferFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 value\n )\n private\n {\n if (token == address(0)) {\n PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n to,\n value,\n new bytes(0)\n );\n } else {\n bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n token,\n 0,\n abi.encodeWithSelector(\n ERC20Token(token).transfer.selector,\n to,\n value\n )\n );\n\n if (response.length > 0) {\n require(\n abi.decode(response, (bool)),\n \"PaymentRegistry: ERC20Token transfer reverted\"\n );\n }\n }\n }\n\n function _transferSplitFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 paymentValue,\n uint256 depositValue\n )\n private\n {\n require(\n depositValue > 0,\n \"PaymentRegistry: invalid deposit value\"\n );\n\n uint256 withdrawValue = paymentValue.sub(depositValue);\n\n require(\n withdrawValue > 0,\n \"PaymentRegistry: invalid withdraw value\"\n );\n\n _transferFromDeposit(\n depositAccount,\n to,\n token,\n withdrawValue\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(to),\n token,\n depositValue\n );\n }\n\n // private functions (views)\n\n function _computeDepositAccountAddress(\n address owner\n )\n private\n view\n returns (address)\n {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n bytes memory creationCode = type(PaymentDepositAccount).creationCode;\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 function _hashDepositWithdrawal(\n address owner,\n address token,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(\n owner,\n token,\n amount\n ));\n }\n\n function _hashPaymentChannelCommit(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n ));\n }\n\n // private functions (pure)\n\n function _computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n private\n pure\n returns (bytes32)\n {\n return keccak256(\n abi.encodePacked(\n sender,\n recipient,\n token,\n uid\n )\n );\n }\n}\n" + }, + "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ław Głogowski \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" + }, + "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" + }, + "src/common/libs/SafeMathLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n" + }, + "src/common/lifecycle/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski \n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n" + }, + "src/common/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ław Głogowski \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" + }, + "src/common/token/ERC20Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n" + }, + "src/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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "src/gateway/GatewayRecipient.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n" + }, + "src/payments/PaymentDepositAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/access/Controlled.sol\";\n\n\n/**\n * @title Payment deposit account\n *\n * @dev Simple account contract with only one method - `executeTransaction`\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentDepositAccount is Controlled {\n /**\n * @dev Public constructor\n */\n constructor() public payable Controlled() {}\n\n /**\n * @notice Allow receives\n */\n receive()\n external\n payable\n {\n //\n }\n\n // external functions\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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \n */\ncontract AccountBase {\n address public registry;\n}\n" + }, + "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" + }, + "src/common/libs/BytesLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski \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" + }, + "src/tokens/WrappedWeiToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski \n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n" + }, + "src/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 \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" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.12;\r\npragma experimental ABIEncoderV2;\r\n\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/**\r\n * @title Gateway\r\n *\r\n * @notice GSN replacement\r\n *\r\n * @author Stanisław Głogowski \r\n */\r\ncontract Gateway is Initializable, SignatureValidator {\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\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 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 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 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 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 // 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}" + }, + "src/ens/ENSController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./resolvers/ENSPubKeyResolver.sol\";\nimport \"./resolvers/ENSTextResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n\n/**\n * @title ENS controller\n *\n * @notice ENS subnode registrar\n *\n * @dev The process of adding root node consists of 3 steps:\n * 1. `submitNode` - should be called from ENS node owner,\n * 2. Change ENS node owner in ENS registry to ENS controller,\n * 3. `verifyNode` - should be called from previous ENS node owner,\n *\n * To register sub node, `msg.sender` need to send valid signature from one of guardian key.\n * Once registration is complete `msg.sender` becoming both node owner and `addr` record value.\n *\n * After registration sub node cannot be replaced.\n *\n * @author Stanisław Głogowski \n */\ncontract ENSController is Guarded, Initializable, SignatureValidator, GatewayRecipient, ENSAddressResolver, ENSNameResolver, ENSPubKeyResolver, ENSTextResolver {\n struct SubNodeRegistration {\n address account;\n bytes32 node;\n bytes32 label;\n }\n\n bytes4 private constant INTERFACE_META_ID = bytes4(keccak256(abi.encodePacked(\"supportsInterface(bytes4)\")));\n\n bytes32 private constant HASH_PREFIX_SUB_NODE_REGISTRATION = keccak256(\n \"SubNodeRegistration(address account,bytes32 node,bytes32 label)\"\n );\n\n ENSRegistry public registry;\n\n mapping(bytes32 => address) public nodeOwners;\n\n // events\n\n /**\n * @dev Emitted when new node is submitted\n * @param node node name hash\n * @param owner owner address\n */\n event NodeSubmitted(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when the existing owner is verified\n * @param node node name hash\n */\n event NodeVerified(\n bytes32 node\n );\n\n /**\n * @dev Emitted when new node is released\n * @param node node name hash\n * @param owner owner address\n */\n event NodeReleased(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when ENS registry address is changed\n * @param registry registry address\n */\n event RegistryChanged(\n address registry\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Guarded() Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSController` contract\n * @param registry_ ENS registry address\n * @param gateway_ gateway address\n */\n function initialize(\n ENSRegistry registry_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n registry = registry_;\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Sets registry\n * @param registry_ registry address\n */\n function setRegistry(\n ENSRegistry registry_\n )\n external\n onlyGuardian\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n require(\n registry_ != registry,\n \"ENSController: registry already set\"\n );\n\n registry = registry_;\n\n emit RegistryChanged(\n address(registry)\n );\n }\n\n /**\n * @notice Submits node\n * @dev Should be called from the current ENS node owner\n * @param node node name hash\n */\n function submitNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == address(0),\n \"ENSController: node already submitted\"\n );\n\n require(\n registry.owner(node) == owner,\n \"ENSController: invalid ens node owner\"\n );\n\n nodeOwners[node] = owner;\n\n emit NodeSubmitted(node, owner);\n }\n\n /**\n * @notice Verifies node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function verifyNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n require(\n registry.owner(node) == address(this),\n \"ENSController: invalid ens node owner\"\n );\n\n _setAddr(node, address(this));\n\n registry.setResolver(node, address(this));\n\n emit NodeVerified(node);\n }\n\n /**\n * @notice Releases node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function releaseNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(this),\n \"ENSController: node doesn't exist\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n registry.setOwner(node, owner);\n\n delete nodeOwners[node];\n\n emit NodeReleased(node, owner);\n }\n\n /**\n * @notice Sync address\n * @param node node name hash\n */\n function syncAddr(\n bytes32 node\n )\n external\n {\n address account = _getContextAccount();\n\n require(\n account == registry.owner(node),\n \"ENSController: caller is not the node owner\"\n );\n\n require(\n registry.resolver(node) == address(this),\n \"ENSController: invalid node resolver\"\n );\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already in sync\"\n );\n\n _setAddr(node, account);\n }\n\n /**\n * @notice Registers sub node\n * @param node node name hash\n * @param label label hash\n * @param guardianSignature guardian signature\n */\n function registerSubNode(\n bytes32 node,\n bytes32 label,\n bytes calldata guardianSignature\n )\n external\n {\n address account = _getContextAccount();\n\n bytes32 messageHash = _hashSubNodeRegistration(\n account,\n node,\n label\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"ENSController: invalid guardian signature\"\n );\n\n bytes32 subNode = keccak256(\n abi.encodePacked(\n node,\n label\n )\n );\n\n require(\n _addr(node) == address(this),\n \"ENSController: invalid node\"\n );\n\n require(\n _addr(subNode) == address(0),\n \"ENSController: label already taken\"\n );\n\n registry.setSubnodeRecord(node, label, address(this), address(this), 0);\n registry.setOwner(subNode, account);\n\n _setAddr(subNode, account);\n }\n\n // external functions (pure)\n function supportsInterface(\n bytes4 interfaceID\n )\n external\n pure\n returns(bool)\n {\n return interfaceID == INTERFACE_META_ID ||\n interfaceID == INTERFACE_ADDR_ID ||\n interfaceID == INTERFACE_ADDRESS_ID ||\n interfaceID == INTERFACE_NAME_ID ||\n interfaceID == INTERFACE_PUB_KEY_ID ||\n interfaceID == INTERFACE_TEXT_ID;\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `SubNodeRegistration` message payload\n * @param subNodeRegistration struct\n * @return hash\n */\n function hashSubNodeRegistration(\n SubNodeRegistration memory subNodeRegistration\n )\n public\n view\n returns (bytes32)\n {\n return _hashSubNodeRegistration(\n subNodeRegistration.account,\n subNodeRegistration.node,\n subNodeRegistration.label\n );\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n override\n view\n returns (bool)\n {\n return registry.owner(node) == _getContextAccount();\n }\n\n // private functions (views)\n\n function _hashSubNodeRegistration(\n address account,\n bytes32 node,\n bytes32 label\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_SUB_NODE_REGISTRATION, abi.encodePacked(\n account,\n node,\n label\n ));\n }\n}\n" + }, + "src/ens/resolvers/ENSAddressResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract address resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/AddrResolver.sol\n */\nabstract contract ENSAddressResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_ADDR_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32)\")));\n bytes4 internal constant INTERFACE_ADDRESS_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32,uint)\")));\n\n uint internal constant COIN_TYPE_ETH = 60;\n\n mapping(bytes32 => mapping(uint => bytes)) internal resolverAddresses;\n\n // events\n\n event AddrChanged(\n bytes32 indexed node,\n address addr\n );\n\n event AddressChanged(\n bytes32 indexed node,\n uint coinType,\n bytes newAddress\n );\n\n // external functions\n\n function setAddr(\n bytes32 node,\n address addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, addr_);\n }\n\n function setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, coinType, addr_);\n }\n\n // external functions (views)\n\n function addr(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return _addr(node);\n }\n\n function addr(\n bytes32 node,\n uint coinType\n )\n external\n view\n returns (bytes memory)\n {\n return resolverAddresses[node][coinType];\n }\n\n // internal functions\n\n function _setAddr(\n bytes32 node,\n address addr_\n )\n internal\n {\n _setAddr(node, COIN_TYPE_ETH, _addressToBytes(addr_));\n }\n\n function _setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n internal\n {\n emit AddressChanged(node, coinType, addr_);\n\n if(coinType == COIN_TYPE_ETH) {\n emit AddrChanged(node, _bytesToAddress(addr_));\n }\n\n resolverAddresses[node][coinType] = addr_;\n }\n\n // internal functions (views)\n\n function _addr(\n bytes32 node\n )\n internal\n view\n returns (address)\n {\n address result;\n\n bytes memory addr_ = resolverAddresses[node][COIN_TYPE_ETH];\n\n if (addr_.length > 0) {\n result = _bytesToAddress(addr_);\n }\n\n return result;\n }\n\n // private function (pure)\n\n function _bytesToAddress(\n bytes memory data\n )\n private\n pure\n returns(address payable)\n {\n address payable result;\n\n require(data.length == 20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 32)), exp(256, 12))\n }\n\n return result;\n }\n\n function _addressToBytes(\n address addr_\n )\n private\n pure\n returns(bytes memory)\n {\n bytes memory result = new bytes(20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(add(result, 32), mul(addr_, exp(256, 12)))\n }\n\n return result;\n }\n}\n" + }, + "src/ens/resolvers/ENSNameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract name resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/NameResolver.sol\n */\nabstract contract ENSNameResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_NAME_ID = bytes4(keccak256(abi.encodePacked(\"name(bytes32)\")));\n\n mapping(bytes32 => string) internal resolverNames;\n\n // events\n\n event NameChanged(\n bytes32 indexed node,\n string name\n );\n\n // external functions\n\n function setName(\n bytes32 node,\n string calldata name\n )\n external\n onlyNodeOwner(node)\n {\n resolverNames[node] = name;\n\n emit NameChanged(node, name);\n }\n\n // external functions (views)\n\n function name(\n bytes32 node\n )\n external\n view\n returns (string memory)\n {\n return resolverNames[node];\n }\n}\n" + }, + "src/ens/resolvers/ENSPubKeyResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract pub key resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/PubkeyResolver.sol\n */\nabstract contract ENSPubKeyResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_PUB_KEY_ID = bytes4(keccak256(abi.encodePacked(\"pubkey(bytes32)\")));\n\n struct PubKey {\n bytes32 x;\n bytes32 y;\n }\n\n mapping(bytes32 => PubKey) internal resolverPubKeys;\n\n // events\n\n event PubkeyChanged(\n bytes32 indexed node,\n bytes32 x,\n bytes32 y\n );\n\n // external functions (views)\n\n function setPubkey(\n bytes32 node,\n bytes32 x,\n bytes32 y\n )\n external\n onlyNodeOwner(node)\n {\n resolverPubKeys[node] = PubKey(x, y);\n\n emit PubkeyChanged(node, x, y);\n }\n\n // external functions (views)\n\n function pubkey(\n bytes32 node\n )\n external\n view\n returns (bytes32 x, bytes32 y)\n {\n return (resolverPubKeys[node].x, resolverPubKeys[node].y);\n }\n}\n" + }, + "src/ens/resolvers/ENSTextResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract text resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/TextResolver.sol\n */\nabstract contract ENSTextResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_TEXT_ID = bytes4(keccak256(abi.encodePacked(\"text(bytes32,string)\")));\n\n mapping(bytes32 => mapping(string => string)) internal resolverTexts;\n\n // events\n\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key\n );\n\n // external functions (views)\n\n function setText(\n bytes32 node,\n string calldata key,\n string calldata value\n )\n external\n onlyNodeOwner(node)\n {\n resolverTexts[node][key] = value;\n\n emit TextChanged(node, key, key);\n }\n\n // external functions (views)\n\n function text(\n bytes32 node,\n string calldata key\n )\n external\n view\n returns (string memory)\n {\n return resolverTexts[node][key];\n }\n}\n" + }, + "src/ens/ENSRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS registry\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\n */\ncontract ENSRegistry {\n struct Record {\n address owner;\n address resolver;\n uint64 ttl;\n }\n\n mapping (bytes32 => Record) private records;\n mapping (address => mapping(address => bool)) private operators;\n\n // events\n\n event NewOwner(\n bytes32 indexed node,\n bytes32 indexed label,\n address owner\n );\n\n event Transfer(\n bytes32 indexed node,\n address owner\n );\n\n event NewResolver(\n bytes32 indexed node,\n address resolver\n );\n\n event NewTTL(\n bytes32 indexed node,\n uint64 ttl\n );\n\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n // modifiers\n\n modifier authorised(\n bytes32 node\n )\n {\n address owner = records[node].owner;\n\n require(\n owner == msg.sender || operators[owner][msg.sender],\n \"ENSRegistry: reverted by authorised modifier\"\n );\n\n _;\n }\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n {\n // solhint-disable-next-line avoid-tx-origin\n records[0x0].owner = tx.origin;\n }\n\n // external functions\n\n function setRecord(\n bytes32 node,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n setOwner(node, owner_);\n\n _setResolverAndTTL(node, resolver_, ttl_);\n }\n\n function setTTL(\n bytes32 node,\n uint64 ttl_\n )\n external\n authorised(node)\n {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n bytes32 subNode = setSubnodeOwner(node, label, owner_);\n\n _setResolverAndTTL(subNode, resolver_, ttl_);\n }\n\n function setApprovalForAll(\n address operator,\n bool approved\n )\n external\n {\n operators[msg.sender][operator] = approved;\n\n emit ApprovalForAll(\n msg.sender,\n operator,\n approved\n );\n }\n\n // external functions (views)\n\n function owner(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n address addr = records[node].owner;\n\n if (addr == address(this)) {\n return address(0x0);\n }\n\n return addr;\n }\n\n function resolver(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return records[node].resolver;\n }\n\n function ttl(\n bytes32 node\n )\n external\n view\n returns (uint64)\n {\n return records[node].ttl;\n }\n\n function recordExists(\n bytes32 node\n )\n external\n view\n returns (bool)\n {\n return records[node].owner != address(0x0);\n }\n\n function isApprovedForAll(\n address owner_,\n address operator\n )\n external\n view\n returns (bool)\n {\n return operators[owner_][operator];\n }\n\n // public functions\n\n function setOwner(\n bytes32 node,\n address owner_\n )\n public\n authorised(node)\n {\n records[node].owner = owner_;\n\n emit Transfer(node, owner_);\n }\n\n function setResolver(\n bytes32 node,\n address resolver_\n )\n public\n authorised(node)\n {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner_\n )\n public\n authorised(node)\n returns(bytes32)\n {\n bytes32 subNode = keccak256(abi.encodePacked(node, label));\n\n records[subNode].owner = owner_;\n\n emit NewOwner(node, label, owner_);\n\n return subNode;\n }\n\n // private functions\n\n function _setResolverAndTTL(\n bytes32 node,\n address resolver_,\n uint64 ttl_\n )\n private\n {\n if (resolver_ != records[node].resolver) {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n if (ttl_ != records[node].ttl) {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n }\n}\n" + }, + "src/ens/resolvers/ENSAbstractResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS abstract resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/ResolverBase.sol\n */\nabstract contract ENSAbstractResolver {\n // modifiers\n\n modifier onlyNodeOwner(bytes32 node)\n {\n require(\n _isNodeOwner(node),\n \"ENSAbstractResolver: reverted by onlyNodeOwner modifier\"\n );\n\n _;\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n virtual\n view\n returns (bool);\n}\n" + }, + "src/ens/ENSReverseRegistrar.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/AddressLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS reverse registrar\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\n */\ncontract ENSReverseRegistrar is Initializable {\n using AddressLib for address;\n\n // namehash('addr.reverse')\n bytes32 public constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n ENSRegistry public registry;\n ENSNameResolver public resolver;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSReverseRegistrar` contract\n * @param registry_ ENS registry address\n * @param resolver_ ENS name resolver address\n */\n function initialize(\n ENSRegistry registry_,\n ENSNameResolver resolver_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n resolver = resolver_;\n }\n\n // external functions\n\n function claim(\n address owner\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, address(0));\n }\n\n function claimWithResolver(\n address owner,\n address resolver_\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, resolver_);\n }\n\n function setName(\n string memory name\n )\n public\n returns (bytes32)\n {\n bytes32 node = _claimWithResolver(address(this), address(resolver));\n\n resolver.setName(node, name);\n\n return node;\n }\n\n // external functions (pure)\n\n function node(\n address addr_\n )\n external\n pure\n returns (bytes32)\n {\n return keccak256(abi.encodePacked(ADDR_REVERSE_NODE, addr_.toSha3Hash()));\n }\n\n // private functions\n\n function _claimWithResolver(\n address owner,\n address resolver_\n )\n private\n returns (bytes32)\n {\n bytes32 label = address(msg.sender).toSha3Hash();\n bytes32 node_ = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n address currentOwner = registry.owner(node_);\n\n if (resolver_ != address(0x0) && resolver_ != registry.resolver(node_)) {\n if (currentOwner != address(this)) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this));\n currentOwner = address(this);\n }\n\n registry.setResolver(node_, resolver_);\n }\n\n // Update the owner if required\n if (currentOwner != owner) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);\n }\n\n return node_;\n }\n}\n" + }, + "src/common/libs/AddressLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Address library\n */\nlibrary AddressLib {\n /**\n * @notice Converts address into sha3 hash\n * @param self address\n * @return sha3 hash\n */\n function toSha3Hash(\n address self\n )\n internal\n pure\n returns (bytes32)\n {\n bytes32 result;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000\n\n for { let i := 40 } gt(i, 0) { } {\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n }\n\n result := keccak256(0, 40)\n }\n\n return result;\n }\n}\n" + }, + "src/ens/ENSHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS helper\n *\n * @author Stanisław Głogowski \n */\ncontract ENSHelper is Initializable {\n ENSRegistry public registry;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSLookupHelper` contract\n * @param registry_ ENS registry address\n */\n function initialize(\n ENSRegistry registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n /**\n * @notice Gets nodes addresses\n * @param nodes array of nodes\n * @return nodes addresses\n */\n function getAddresses(\n bytes32[] memory nodes\n )\n external\n view\n returns (address[] memory)\n {\n uint nodesLen = nodes.length;\n address[] memory result = new address[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getAddress(nodes[i]);\n }\n\n return result;\n }\n\n /**\n * @notice Gets nodes names\n * @param nodes array of nodes\n * @return nodes names\n */\n function getNames(\n bytes32[] memory nodes\n )\n external\n view\n returns (string[] memory)\n {\n uint nodesLen = nodes.length;\n string[] memory result = new string[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getName(nodes[i]);\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getAddress(\n bytes32 node\n )\n private\n view\n returns (address)\n {\n address result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSAddressResolver(resolver).addr(node) returns (address addr) {\n result = addr;\n } catch {\n //\n }\n }\n\n return result;\n }\n\n function _getName(\n bytes32 node\n )\n private\n view\n returns (string memory)\n {\n string memory result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSNameResolver(resolver).name(node) returns (string memory name) {\n result = name;\n } catch {\n //\n }\n }\n\n return result;\n }\n}\n" + }, + "src/common/account/AccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../lifecycle/Initializable.sol\";\nimport \"./AccountBase.sol\";\nimport \"./AccountRegistry.sol\";\n\n\n/**\n * @title Account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1 is Initializable, AccountBase {\n bytes32 constant private ERC777_TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(abi.encodePacked(\"ERC777TokensRecipient\"));\n bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n bytes4 constant private ERC1271_VALID_MESSAGE_HASH_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes32,bytes)\")));\n bytes4 constant private ERC1271_VALID_MESSAGE_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes,bytes)\")));\n bytes4 constant private ERC1271_INVALID_SIGNATURE = 0xffffffff;\n\n /**\n * @dev Internal constructor\n */\n constructor() internal Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `AccountImplementation` contract\n * @param registry_ registry address\n */\n function initialize(\n address registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n // ERC1820\n\n function canImplementInterfaceForAddress(\n bytes32 interfaceHash,\n address addr\n )\n external\n view\n returns(bytes32)\n {\n bytes32 result;\n\n if (interfaceHash == ERC777_TOKENS_RECIPIENT_INTERFACE_HASH && addr == address(this)) {\n result = ERC1820_ACCEPT_MAGIC;\n }\n\n return result;\n }\n\n // ERC1271\n\n function isValidSignature(\n bytes32 messageHash,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), messageHash, signature)\n ? ERC1271_VALID_MESSAGE_HASH_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n function isValidSignature(\n bytes calldata message,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), message, signature)\n ? ERC1271_VALID_MESSAGE_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n // external functions (pure)\n\n // ERC721\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC721Received.selector;\n }\n\n // ERC1155\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC1155Received.selector;\n }\n\n // ERC777\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n )\n external\n pure\n {}\n}\n" + }, + "src/personal/PersonalAccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/account/AccountImplementationV1.sol\";\n\n\n/**\n * @title Personal account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\n\n /**\n * @dev Public constructor\n */\n constructor() public AccountImplementationV1() {}\n}\n" + }, + "src/common/account/mocks/AccountImplementationV1Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountImplementationV1.sol\";\n\n\n/**\n * @title Account implementation mock (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1Mock is AccountImplementationV1 {\n /**\n * @dev Public constructor\n * @param registry_ account registry address\n */\n constructor(\n address registry_\n )\n public\n AccountImplementationV1()\n {\n registry = registry_;\n }\n}\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/sokol/BalancesHelperV2.json b/deployments/sokol/BalancesHelperV2.json new file mode 100644 index 00000000..9420b894 --- /dev/null +++ b/deployments/sokol/BalancesHelperV2.json @@ -0,0 +1,160 @@ +{ + "address": "0xe5A160F89f330cc933816E896a3F36376DE0a835", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "AccountZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getBalances", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getSuperfluidWrappedTokenBalances", + "outputs": [ + { + "internalType": "int256[]", + "name": "", + "type": "int256[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x3c525b35e3571587d7b03d7c24a687a3b99a76a81e6ea76516c5d54c0b88349b", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "contractAddress": null, + "transactionIndex": 29, + "gasUsed": "964203", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x6b2e6de942c2bdd44a65ec5a4dc282be306be282b96485ea7a70dfd0a867f1ad", + "transactionHash": "0x3c525b35e3571587d7b03d7c24a687a3b99a76a81e6ea76516c5d54c0b88349b", + "logs": [], + "blockNumber": 27513211, + "cumulativeGasUsed": "2933215", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "893c7c8579088197a1acbd2718e7b759", + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"AccountZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getSuperfluidWrappedTokenBalances\",\"outputs\":[{\"internalType\":\"int256[]\",\"name\":\"\",\"type\":\"int256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"details\":\"Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue\",\"params\":{\"accounts\":\"= Array of accounts addresses\",\"tokens\":\"= Array of tokens addresses\"},\"returns\":{\"_0\":\"One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"AccountZeroAddress(address,address)\":[{\"notice\":\"Custom errors to handle address(0)\"}]},\"kind\":\"user\",\"methods\":{\"getBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple ERC20 tokens.\"},\"getSuperfluidWrappedTokenBalances(address[],address[])\":{\"notice\":\"Returns balances of accounts for multiple Wrapped Super Tokens.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/common/helpers/BalancesHelperV2.sol\":\"BalancesHelperV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0x6ebf1944ab804b8660eb6fc52f9fe84588cee01c2566a69023e59497e7d27f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperAgreement.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperfluidToken } from \\\"./ISuperfluidToken.sol\\\";\\n\\n/**\\n * @title Super agreement interface\\n * @author Superfluid\\n */\\ninterface ISuperAgreement {\\n\\n /**\\n * @dev Get the type of the agreement class\\n */\\n function agreementType() external view returns (bytes32);\\n\\n /**\\n * @dev Calculate the real-time balance for the account of this agreement class\\n * @param account Account the state belongs to\\n * @param time Time used for the calculation\\n * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement\\n * @return deposit Account deposit amount of this agreement\\n * @return owedDeposit Account owed deposit amount of this agreement\\n */\\n function realtimeBalanceOf(\\n ISuperfluidToken token,\\n address account,\\n uint256 time\\n )\\n external\\n view\\n returns (\\n int256 dynamicBalance,\\n uint256 deposit,\\n uint256 owedDeposit\\n );\\n\\n}\\n\",\"keccak256\":\"0xc3a6a907245116bcecc70fe4b207454012e8ce4fa190228fb8bbe39e0b1bc5cf\",\"license\":\"AGPLv3\"},\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\":{\"content\":\"// SPDX-License-Identifier: AGPLv3\\npragma solidity >= 0.8.0;\\n\\nimport { ISuperAgreement } from \\\"./ISuperAgreement.sol\\\";\\n\\n\\n/**\\n * @title Superfluid token interface\\n * @author Superfluid\\n */\\ninterface ISuperfluidToken {\\n\\n /**************************************************************************\\n * Basic information\\n *************************************************************************/\\n\\n /**\\n * @dev Get superfluid host contract address\\n */\\n function getHost() external view returns(address host);\\n\\n /**\\n * @dev Encoded liquidation type data mainly used for handling stack to deep errors\\n *\\n * Note:\\n * - version: 1\\n * - liquidationType key:\\n * - 0 = reward account receives reward (PIC period)\\n * - 1 = liquidator account receives reward (Pleb period)\\n * - 2 = liquidator account receives reward (Pirate period/bailout)\\n */\\n struct LiquidationTypeData {\\n uint256 version;\\n uint8 liquidationType;\\n }\\n\\n /**************************************************************************\\n * Real-time balance functions\\n *************************************************************************/\\n\\n /**\\n * @dev Calculate the real balance of a user, taking in consideration all agreements of the account\\n * @param account for the query\\n * @param timestamp Time of balance\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOf(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit);\\n\\n /**\\n * @notice Calculate the realtime balance given the current host.getNow() value\\n * @dev realtimeBalanceOf with timestamp equals to block timestamp\\n * @param account for the query\\n * @return availableBalance Real-time balance\\n * @return deposit Account deposit\\n * @return owedDeposit Account owed Deposit\\n */\\n function realtimeBalanceOfNow(\\n address account\\n )\\n external view\\n returns (\\n int256 availableBalance,\\n uint256 deposit,\\n uint256 owedDeposit,\\n uint256 timestamp);\\n\\n /**\\n * @notice Check if account is critical\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is critical (should use future)\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCritical(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is critical now (current host.getNow())\\n * @dev A critical account is when availableBalance < 0\\n * @param account The account to check\\n * @return isCritical Whether the account is critical\\n */\\n function isAccountCriticalNow(\\n address account\\n )\\n external view\\n returns(bool isCritical);\\n\\n /**\\n * @notice Check if account is solvent\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @param timestamp The time we'd like to check if the account is solvent (should use future)\\n * @return isSolvent\\n */\\n function isAccountSolvent(\\n address account,\\n uint256 timestamp\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Check if account is solvent now\\n * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\\n * @param account The account to check\\n * @return isSolvent\\n */\\n function isAccountSolventNow(\\n address account\\n )\\n external view\\n returns(bool isSolvent);\\n\\n /**\\n * @notice Get a list of agreements that is active for the account\\n * @dev An active agreement is one that has state for the account\\n * @param account Account to query\\n * @return activeAgreements List of accounts that have non-zero states for the account\\n */\\n function getAccountActiveAgreements(address account)\\n external view\\n returns(ISuperAgreement[] memory activeAgreements);\\n\\n\\n /**************************************************************************\\n * Super Agreement hosting functions\\n *************************************************************************/\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function createAgreement(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement created event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementCreated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Get data of the agreement\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @return data Data of the agreement\\n */\\n function getAgreementData(\\n address agreementClass,\\n bytes32 id,\\n uint dataLength\\n )\\n external view\\n returns(bytes32[] memory data);\\n\\n /**\\n * @dev Create a new agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n function updateAgreementData(\\n bytes32 id,\\n bytes32[] calldata data\\n )\\n external;\\n /**\\n * @dev Agreement updated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param data Agreement data\\n */\\n event AgreementUpdated(\\n address indexed agreementClass,\\n bytes32 id,\\n bytes32[] data\\n );\\n\\n /**\\n * @dev Close the agreement\\n * @param id Agreement ID\\n */\\n function terminateAgreement(\\n bytes32 id,\\n uint dataLength\\n )\\n external;\\n /**\\n * @dev Agreement terminated event\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n */\\n event AgreementTerminated(\\n address indexed agreementClass,\\n bytes32 id\\n );\\n\\n /**\\n * @dev Update agreement state slot\\n * @param account Account to be updated\\n *\\n * NOTE\\n * - To clear the storage out, provide zero-ed array of intended length\\n */\\n function updateAgreementStateSlot(\\n address account,\\n uint256 slotId,\\n bytes32[] calldata slotData\\n )\\n external;\\n /**\\n * @dev Agreement account state updated event\\n * @param agreementClass Contract address of the agreement\\n * @param account Account updated\\n * @param slotId slot id of the agreement state\\n */\\n event AgreementStateUpdated(\\n address indexed agreementClass,\\n address indexed account,\\n uint256 slotId\\n );\\n\\n /**\\n * @dev Get data of the slot of the state of an agreement\\n * @param agreementClass Contract address of the agreement\\n * @param account Account to query\\n * @param slotId slot id of the state\\n * @param dataLength length of the state data\\n */\\n function getAgreementStateSlot(\\n address agreementClass,\\n address account,\\n uint256 slotId,\\n uint dataLength\\n )\\n external view\\n returns (bytes32[] memory slotData);\\n\\n /**\\n * @notice Settle balance from an account by the agreement\\n * @dev The agreement needs to make sure that the balance delta is balanced afterwards\\n * @param account Account to query.\\n * @param delta Amount of balance delta to be settled\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function settleBalance(\\n address account,\\n int256 delta\\n )\\n external;\\n\\n /**\\n * @dev Make liquidation payouts (v2)\\n * @param id Agreement ID\\n * @param liquidationTypeData Data regarding the version of the liquidation schema and the type\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount\\n * @param targetAccount Account of the stream sender\\n * @param rewardAmount The amount the reward recepient account will receive\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n *\\n * - If a bailout is required (bailoutAmount > 0)\\n * - the actual reward (single deposit) goes to the executor,\\n * - while the reward account becomes the bailout account\\n * - total bailout include: bailout amount + reward amount\\n * - the targetAccount will be bailed out\\n * - If a bailout is not required\\n * - the targetAccount will pay the rewardAmount\\n * - the liquidator (reward account in PIC period) will receive the rewardAmount\\n *\\n * Modifiers:\\n * - onlyAgreement\\n */\\n function makeLiquidationPayoutsV2\\n (\\n bytes32 id,\\n bytes memory liquidationTypeData,\\n address liquidatorAccount,\\n bool useDefaultRewardAccount,\\n address targetAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta\\n ) external;\\n /**\\n * @dev Agreement liquidation event v2 (including agent account)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param liquidatorAccount Address of the executor of the liquidation\\n * @param targetAccount Account of the stream sender\\n * @param rewardAccount Account that collects the reward or bails out insolvent accounts\\n * @param rewardAmount The amount the reward recipient account balance should change by\\n * @param targetAccountBalanceDelta The amount the sender account balance should change by\\n * @param liquidationTypeData The encoded liquidation type data including the version (how to decode)\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if the agreement is liquidated during the PIC period\\n * - the rewardAccount will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount\\n * - the targetAccount will pay for the rewardAmount\\n * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent\\n * - the liquidatorAccount will get the rewardAmount (remaining deposit)\\n * - the targetAccount will pay for the rewardAmount\\n * - if the targetAccount is insolvent\\n * - the liquidatorAccount will get the rewardAmount (single deposit)\\n * - the rewardAccount will pay for both the rewardAmount and bailoutAmount\\n * - the targetAccount will receive the bailoutAmount\\n */\\n event AgreementLiquidatedV2(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed liquidatorAccount,\\n address indexed targetAccount,\\n address rewardAccount,\\n uint256 rewardAmount,\\n int256 targetAccountBalanceDelta,\\n bytes liquidationTypeData\\n );\\n\\n /**************************************************************************\\n * Function modifiers for access control and parameter validations\\n *\\n * While they cannot be explicitly stated in function definitions, they are\\n * listed in function definition comments instead for clarity.\\n *\\n * NOTE: solidity-coverage not supporting it\\n *************************************************************************/\\n\\n /// @dev The msg.sender must be host contract\\n //modifier onlyHost() virtual;\\n\\n /// @dev The msg.sender must be a listed agreement.\\n //modifier onlyAgreement() virtual;\\n\\n /**************************************************************************\\n * DEPRECATED\\n *************************************************************************/\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy)\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param rewardAccount Account that collect the reward\\n * @param rewardAmount Amount of liquidation reward\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event AgreementLiquidated(\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed rewardAccount,\\n uint256 rewardAmount\\n );\\n\\n /**\\n * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy)\\n * @param bailoutAccount Account that bailout the penalty account\\n * @param bailoutAmount Amount of account bailout\\n *\\n * NOTE:\\n *\\n * [DEPRECATED] Use AgreementLiquidatedV2 instead\\n */\\n event Bailout(\\n address indexed bailoutAccount,\\n uint256 bailoutAmount\\n );\\n\\n /**\\n * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2)\\n * @param liquidatorAccount Account of the agent that performed the liquidation.\\n * @param agreementClass Contract address of the agreement\\n * @param id Agreement ID\\n * @param penaltyAccount Account of the agreement to be penalized\\n * @param bondAccount Account that collect the reward or bailout accounts\\n * @param rewardAmount Amount of liquidation reward\\n * @param bailoutAmount Amount of liquidation bailouot\\n *\\n * NOTE:\\n * Reward account rule:\\n * - if bailout is equal to 0, then\\n * - the bondAccount will get the rewardAmount,\\n * - the penaltyAccount will pay for the rewardAmount.\\n * - if bailout is larger than 0, then\\n * - the liquidatorAccount will get the rewardAmouont,\\n * - the bondAccount will pay for both the rewardAmount and bailoutAmount,\\n * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.\\n */\\n event AgreementLiquidatedBy(\\n address liquidatorAccount,\\n address indexed agreementClass,\\n bytes32 id,\\n address indexed penaltyAccount,\\n address indexed bondAccount,\\n uint256 rewardAmount,\\n uint256 bailoutAmount\\n );\\n}\\n\",\"keccak256\":\"0x9189eaba9e856cc4932ea29eeaf4e89a09448dde13860591691ec122856fdc75\",\"license\":\"AGPLv3\"},\"src/common/helpers/BalancesHelperV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\n// solhint-disable-next-line\\r\\npragma solidity 0.8.4;\\r\\n\\r\\n/// @title BalancesHelperV2\\r\\n/// @author Luke Wickens \\r\\n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\\r\\n\\r\\nimport {ISuperfluidToken} from \\\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\\\";\\r\\nimport {IERC20} from \\\"@openzeppelin/contracts/interfaces/IERC20.sol\\\";\\r\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\r\\n\\r\\ncontract BalancesHelperV2 {\\r\\n using Address for address;\\r\\n\\r\\n /// @notice Custom errors to handle address(0)\\r\\n error AccountZeroAddress(address account, address token);\\r\\n error TokenZeroAddress(address account, address token);\\r\\n\\r\\n constructor() {}\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple ERC20 tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getBalances(address[] calldata accounts, address[] calldata tokens)\\r\\n external\\r\\n view\\r\\n returns (uint256[] memory)\\r\\n {\\r\\n uint256[] memory result = new uint256[](\\r\\n accounts.length * tokens.length\\r\\n );\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getBalance(accounts[i], tokens[j]);\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\\r\\n /// @dev Error thrown if: account or token address is address(0),\\r\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\r\\n /// @param accounts = Array of accounts addresses\\r\\n /// @param tokens = Array of tokens addresses\\r\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\r\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\r\\n\\r\\n function getSuperfluidWrappedTokenBalances(\\r\\n address[] calldata accounts,\\r\\n address[] calldata tokens\\r\\n ) external view returns (int256[] memory) {\\r\\n int256[] memory result = new int256[](accounts.length * tokens.length);\\r\\n\\r\\n for (uint256 i; i < accounts.length; i++) {\\r\\n for (uint256 j; j < tokens.length; j++) {\\r\\n uint256 index = j + (tokens.length * i);\\r\\n result[index] = _getSuperfluidWrappedTokenBalance(\\r\\n accounts[i],\\r\\n tokens[j]\\r\\n );\\r\\n }\\r\\n }\\r\\n return result;\\r\\n }\\r\\n\\r\\n /// Private fuctions\\r\\n\\r\\n /// @notice Returns balance of account for an ERC20 token.\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return balance of account as uint256.\\r\\n\\r\\n function _getBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (uint256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\\r\\n );\\r\\n\\r\\n return abi.decode(returnedData, (uint256));\\r\\n }\\r\\n\\r\\n /// @notice Returns real balance of a user, taking into consideration all agreements of account\\r\\n /// @dev Error thrown if: account or token address is address(0)\\r\\n /// @param account = account address\\r\\n /// @param token = tokens address\\r\\n /// @return available balance of account as int256.\\r\\n\\r\\n function _getSuperfluidWrappedTokenBalance(address account, address token)\\r\\n private\\r\\n view\\r\\n returns (int256)\\r\\n {\\r\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\r\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\r\\n\\r\\n bytes memory returnedData = token.functionStaticCall(\\r\\n abi.encodeWithSelector(\\r\\n ISuperfluidToken(token).realtimeBalanceOfNow.selector,\\r\\n account\\r\\n )\\r\\n );\\r\\n\\r\\n (int256 availableBalance, , , ) = abi.decode(\\r\\n returnedData,\\r\\n (int256, uint256, uint256, uint256)\\r\\n );\\r\\n return availableBalance;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xee88323570149a5d9e569da056eaa089cf4baacfb3713a0dd282090b1d0847d2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061108a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", + "devdoc": { + "kind": "dev", + "methods": { + "getBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "details": "Error thrown if: account or token address is address(0), large arrays of accounts/tokens are passed in could cause gas block limit issue", + "params": { + "accounts": "= Array of accounts addresses", + "tokens": "= Array of tokens addresses" + }, + "returns": { + "_0": "One-dimensional that's accounts.length * tokens.length long. The array is ordered by all of accounts[0] token balances, then accounts[1] etc." + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "AccountZeroAddress(address,address)": [ + { + "notice": "Custom errors to handle address(0)" + } + ] + }, + "kind": "user", + "methods": { + "getBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple ERC20 tokens." + }, + "getSuperfluidWrappedTokenBalances(address[],address[])": { + "notice": "Returns balances of accounts for multiple Wrapped Super Tokens." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sokol/GatewayV2.json b/deployments/sokol/GatewayV2.json new file mode 100644 index 00000000..dc82086d --- /dev/null +++ b/deployments/sokol/GatewayV2.json @@ -0,0 +1,926 @@ +{ + "address": "0xBEd52610518788B931f7825301909e7616273d47", + "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": "0xc39568a814d9b8e6137049bc34403b6940bdec03545f304778558ff1444ee393", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "contractAddress": null, + "transactionIndex": 48, + "gasUsed": "2822044", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf4ec2afcfc970c2032a1914c510c2b8799957c43640a937f982a5f0540888102", + "transactionHash": "0xc39568a814d9b8e6137049bc34403b6940bdec03545f304778558ff1444ee393", + "logs": [], + "blockNumber": 27513212, + "cumulativeGasUsed": "6081320", + "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 \",\"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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 \\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 ", + "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" + } + } + } +} \ No newline at end of file diff --git a/deployments/sokol/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json b/deployments/sokol/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json new file mode 100644 index 00000000..fa380d29 --- /dev/null +++ b/deployments/sokol/solcInputs/c3a4dcb3b63a7a4eb038de81f94876c9.json @@ -0,0 +1,142 @@ +{ + "language": "Solidity", + "sources": { + "src/payments/PaymentRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./PaymentDepositAccount.sol\";\n\n\n/**\n * @title Payment registry\n *\n * @notice A registry for payment and payment channels\n *\n * @dev the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message.\n * Process will be rejected when any of senders channels will be committed.\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct Deposit {\n address account;\n mapping(address => uint256) withdrawnAmount;\n mapping(address => uint256) exitLockedUntil;\n }\n\n struct PaymentChannel {\n uint256 committedAmount;\n }\n\n struct DepositWithdrawal {\n address owner;\n address token;\n uint256 amount;\n }\n\n struct PaymentChannelCommit {\n address sender;\n address recipient;\n address token;\n bytes32 uid;\n uint256 blockNumber;\n uint256 amount;\n }\n\n uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;\n\n bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(\n \"DepositWithdrawal(address owner,address token,uint256 amount)\"\n );\n bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(\n \"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n uint256 public depositExitLockPeriod;\n\n mapping(address => Deposit) private deposits;\n mapping(bytes32 => PaymentChannel) private paymentChannels;\n\n // events\n\n /**\n * @dev Emitted when the deposit account is deployed\n * @param depositAccount deposit account address\n * @param owner owner address\n */\n event DepositAccountDeployed(\n address depositAccount,\n address owner\n );\n\n /**\n * @dev Emitted when the deposit exist is requested\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param lockedUntil deposit exist locked util time\n */\n event DepositExitRequested(\n address depositAccount,\n address owner,\n address token,\n uint256 lockedUntil\n );\n\n /**\n * @dev Emitted when the deposit exist is completed\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount deposit exist amount\n */\n event DepositExitCompleted(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the deposit exist is rejected\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n */\n event DepositExitRejected(\n address depositAccount,\n address owner,\n address token\n );\n\n /**\n * @dev Emitted when the deposit has been withdrawn\n * @param depositAccount deposit account address\n * @param owner owner address\n * @param token token address\n * @param amount withdrawn amount\n */\n event DepositWithdrawn(\n address depositAccount,\n address owner,\n address token,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment channel has been committed\n * @param hash channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @param amount committed amount\n */\n event PaymentChannelCommitted(\n bytes32 hash,\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 amount\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentWithdrawn(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been deposited\n * @param channelHash channel hash\n * @param value payment value\n */\n event PaymentDeposited(\n bytes32 channelHash,\n uint256 value\n );\n\n /**\n * @dev Emitted when the payment has been withdrawn and deposited (split)\n * @param channelHash channel hash\n * @param totalValue payment total value\n * @param depositValue payment deposited value\n */\n event PaymentSplit(\n bytes32 channelHash,\n uint256 totalValue,\n uint256 depositValue\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initialize `PaymentRegistry` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n * @param depositExitLockPeriod_ deposit exit lock period\n * @param guardians_ array of guardians addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_,\n uint256 depositExitLockPeriod_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n if (depositExitLockPeriod_ == 0) {\n depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;\n } else {\n depositExitLockPeriod = depositExitLockPeriod_;\n }\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Deploys deposit account\n * @param owner owner address\n */\n function deployDepositAccount(\n address owner\n )\n external\n {\n _deployDepositAccount(owner);\n }\n\n /**\n * @notice Requests deposit exit\n * @param token token address\n */\n function requestDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil == 0,\n \"PaymentRegistry: deposit exit already requested\"\n );\n\n _deployDepositAccount(owner);\n\n // solhint-disable-next-line not-rely-on-time\n lockedUntil = now.add(depositExitLockPeriod);\n\n deposits[owner].exitLockedUntil[token] = lockedUntil;\n\n emit DepositExitRequested(\n deposits[owner].account,\n owner,\n token,\n lockedUntil\n );\n }\n\n /**\n * @notice Processes deposit exit\n * @param token token address\n */\n function processDepositExit(\n address token\n )\n external\n {\n address owner = _getContextAccount();\n uint256 lockedUntil = deposits[owner].exitLockedUntil[token];\n\n require(\n lockedUntil != 0,\n \"PaymentRegistry: deposit exit not requested\"\n );\n\n require(\n // solhint-disable-next-line not-rely-on-time\n lockedUntil <= now,\n \"PaymentRegistry: deposit exit locked\"\n );\n\n deposits[owner].exitLockedUntil[token] = 0;\n\n address depositAccount = deposits[owner].account;\n uint256 depositValue;\n\n if (token == address(0)) {\n depositValue = depositAccount.balance;\n } else {\n depositValue = ERC20Token(token).balanceOf(depositAccount);\n }\n\n _transferFromDeposit(\n depositAccount,\n owner,\n token,\n depositValue\n );\n\n emit DepositExitCompleted(\n depositAccount,\n owner,\n token,\n depositValue\n );\n }\n\n /**\n * @notice Withdraws deposit\n * @param token token address\n * @param amount amount to withdraw\n * @param guardianSignature guardian signature\n */\n function withdrawDeposit(\n address token,\n uint256 amount,\n bytes calldata guardianSignature\n )\n external\n {\n address owner = _getContextAccount();\n uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);\n\n require(\n value > 0,\n \"PaymentRegistry: invalid amount\"\n );\n\n bytes32 messageHash = _hashDepositWithdrawal(\n owner,\n token,\n amount\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n deposits[owner].withdrawnAmount[token] = amount;\n\n _verifyDepositExitOrDeployAccount(owner, token);\n\n _transferFromDeposit(\n deposits[owner].account,\n owner,\n token,\n value\n );\n\n emit DepositWithdrawn(\n deposits[owner].account,\n owner,\n token,\n amount\n );\n }\n\n /**\n * @notice Commits payment channel and withdraw payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndWithdraw(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue\n );\n\n emit PaymentWithdrawn(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel and deposit payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndDeposit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(recipient),\n token,\n paymentValue\n );\n\n emit PaymentDeposited(hash, paymentValue);\n }\n\n /**\n * @notice Commits payment channel, withdraws and deposits (split) payment\n * @param sender sender address\n * @param token token address\n * @param uid unique channel id\n * @param blockNumber block number\n * @param amount amount to commit\n * @param depositPaymentValue amount to deposit\n * @param senderSignature sender signature\n * @param guardianSignature guardian signature\n */\n function commitPaymentChannelAndSplit(\n address sender,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n uint256 depositPaymentValue,\n bytes calldata senderSignature,\n bytes calldata guardianSignature\n )\n external\n {\n address recipient = _getContextAccount();\n\n (bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount,\n senderSignature,\n guardianSignature\n );\n\n _transferSplitFromDeposit(\n depositAccount,\n recipient,\n token,\n paymentValue,\n depositPaymentValue\n );\n\n emit PaymentSplit(hash, paymentValue, depositPaymentValue);\n }\n\n // external functions (views)\n\n /**\n * @notice Computes deposit account address\n * @param owner owner address\n * @return deposit account address\n */\n function computeDepositAccountAddress(\n address owner\n )\n external\n view\n returns (address)\n {\n return _computeDepositAccountAddress(owner);\n }\n\n /**\n * @notice Checks if deposit account is deployed\n * @param owner owner address\n * @return true when deposit account is deployed\n */\n function isDepositAccountDeployed(\n address owner\n )\n external\n view\n returns (bool)\n {\n return deposits[owner].account != address(0);\n }\n\n /**\n * @notice Gets deposit exit locked until time\n * @param owner owner address\n * @param token token address\n * @return locked until time\n */\n function getDepositExitLockedUntil(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].exitLockedUntil[token];\n }\n\n /**\n * @notice Gets deposit withdrawn amount\n * @param owner owner address\n * @param token token address\n * @return withdrawn amount\n */\n function getDepositWithdrawnAmount(\n address owner,\n address token\n )\n external\n view\n returns (uint256)\n {\n return deposits[owner].withdrawnAmount[token];\n }\n\n /**\n * @notice Gets payment channel committed amount\n * @param hash payment channel hash\n * @return committed amount\n */\n function getPaymentChannelCommittedAmount(\n bytes32 hash\n )\n external\n view\n returns (uint256)\n {\n return paymentChannels[hash].committedAmount;\n }\n\n // external functions (pure)\n\n /**\n * @notice Computes payment channel hash\n * @param sender sender address\n * @param recipient recipient address\n * @param token token address\n * @param uid unique channel id\n * @return hash\n */\n function computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n external\n pure\n returns (bytes32)\n {\n return _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DepositWithdrawal` message payload\n * @param depositWithdrawal struct\n * @return hash\n */\n function hashDepositWithdrawal(\n DepositWithdrawal memory depositWithdrawal\n )\n public\n view\n returns (bytes32)\n {\n return _hashDepositWithdrawal(\n depositWithdrawal.owner,\n depositWithdrawal.token,\n depositWithdrawal.amount\n );\n }\n\n /**\n * @notice Hashes `PaymentChannelCommit` message payload\n * @param paymentChannelCommit struct\n * @return hash\n */\n function hashPaymentChannelCommit(\n PaymentChannelCommit memory paymentChannelCommit\n )\n public\n view\n returns (bytes32)\n {\n return _hashPaymentChannelCommit(\n paymentChannelCommit.sender,\n paymentChannelCommit.recipient,\n paymentChannelCommit.token,\n paymentChannelCommit.uid,\n paymentChannelCommit.blockNumber,\n paymentChannelCommit.amount\n );\n }\n\n // private functions\n\n function _deployDepositAccount(\n address owner\n )\n private\n {\n if (deposits[owner].account == address(0)) {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());\n\n emit DepositAccountDeployed(\n deposits[owner].account,\n owner\n );\n }\n }\n\n function _verifyDepositExitOrDeployAccount(\n address owner,\n address token\n )\n private\n {\n if (deposits[owner].exitLockedUntil[token] > 0) {\n deposits[owner].exitLockedUntil[token] = 0;\n\n emit DepositExitRejected(\n deposits[owner].account,\n owner,\n token\n );\n } else {\n _deployDepositAccount(owner);\n }\n }\n\n function _commitPaymentChannel(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount,\n bytes memory senderSignature,\n bytes memory guardianSignature\n )\n private\n returns (bytes32 hash, address depositAccount, uint256 paymentValue)\n {\n bytes32 messageHash = _hashPaymentChannelCommit(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n );\n\n if (senderSignature.length == 0) {\n require(\n externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),\n \"PaymentRegistry: invalid guardian signature\"\n );\n } else {\n address signer = messageHash.recoverAddress(senderSignature);\n\n if (sender != signer) {\n require(\n personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||\n externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),\n \"PaymentRegistry: invalid sender signature\"\n );\n }\n }\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"PaymentRegistry: invalid guardian signature\"\n );\n\n hash = _computePaymentChannelHash(\n sender,\n recipient,\n token,\n uid\n );\n\n /// @dev calc payment value\n paymentValue = amount.sub(paymentChannels[hash].committedAmount);\n\n require(\n paymentValue != 0,\n \"PaymentRegistry: invalid payment value\"\n );\n\n paymentChannels[hash].committedAmount = amount;\n\n _verifyDepositExitOrDeployAccount(sender, token);\n\n depositAccount = deposits[sender].account;\n\n emit PaymentChannelCommitted(\n hash,\n sender,\n recipient,\n token,\n uid,\n amount\n );\n\n return (hash, depositAccount, paymentValue);\n }\n\n function _transferFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 value\n )\n private\n {\n if (token == address(0)) {\n PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n to,\n value,\n new bytes(0)\n );\n } else {\n bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(\n token,\n 0,\n abi.encodeWithSelector(\n ERC20Token(token).transfer.selector,\n to,\n value\n )\n );\n\n if (response.length > 0) {\n require(\n abi.decode(response, (bool)),\n \"PaymentRegistry: ERC20Token transfer reverted\"\n );\n }\n }\n }\n\n function _transferSplitFromDeposit(\n address depositAccount,\n address to,\n address token,\n uint256 paymentValue,\n uint256 depositValue\n )\n private\n {\n require(\n depositValue > 0,\n \"PaymentRegistry: invalid deposit value\"\n );\n\n uint256 withdrawValue = paymentValue.sub(depositValue);\n\n require(\n withdrawValue > 0,\n \"PaymentRegistry: invalid withdraw value\"\n );\n\n _transferFromDeposit(\n depositAccount,\n to,\n token,\n withdrawValue\n );\n\n _transferFromDeposit(\n depositAccount,\n _computeDepositAccountAddress(to),\n token,\n depositValue\n );\n }\n\n // private functions (views)\n\n function _computeDepositAccountAddress(\n address owner\n )\n private\n view\n returns (address)\n {\n bytes32 salt = keccak256(\n abi.encodePacked(\n owner\n )\n );\n\n bytes memory creationCode = type(PaymentDepositAccount).creationCode;\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 function _hashDepositWithdrawal(\n address owner,\n address token,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(\n owner,\n token,\n amount\n ));\n }\n\n function _hashPaymentChannelCommit(\n address sender,\n address recipient,\n address token,\n bytes32 uid,\n uint256 blockNumber,\n uint256 amount\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(\n sender,\n recipient,\n token,\n uid,\n blockNumber,\n amount\n ));\n }\n\n // private functions (pure)\n\n function _computePaymentChannelHash(\n address sender,\n address recipient,\n address token,\n bytes32 uid\n )\n private\n pure\n returns (bytes32)\n {\n return keccak256(\n abi.encodePacked(\n sender,\n recipient,\n token,\n uid\n )\n );\n }\n}\n" + }, + "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ław Głogowski \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" + }, + "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" + }, + "src/common/libs/SafeMathLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n" + }, + "src/common/lifecycle/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski \n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n" + }, + "src/common/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ław Głogowski \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" + }, + "src/common/token/ERC20Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n" + }, + "src/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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "src/gateway/GatewayRecipient.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n" + }, + "src/payments/PaymentDepositAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/access/Controlled.sol\";\n\n\n/**\n * @title Payment deposit account\n *\n * @dev Simple account contract with only one method - `executeTransaction`\n *\n * @author Stanisław Głogowski \n */\ncontract PaymentDepositAccount is Controlled {\n /**\n * @dev Public constructor\n */\n constructor() public payable Controlled() {}\n\n /**\n * @notice Allow receives\n */\n receive()\n external\n payable\n {\n //\n }\n\n // external functions\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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \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" + }, + "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ław Głogowski \n */\ncontract AccountBase {\n address public registry;\n}\n" + }, + "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" + }, + "src/common/libs/BytesLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski \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" + }, + "src/tokens/WrappedWeiToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski \n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n" + }, + "src/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 \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" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.12;\r\npragma experimental ABIEncoderV2;\r\n\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/**\r\n * @title Gateway\r\n *\r\n * @notice GSN replacement\r\n *\r\n * @author Stanisław Głogowski \r\n */\r\ncontract Gateway is Initializable, SignatureValidator {\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\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 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 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 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 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 // 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}" + }, + "src/ens/ENSController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/access/Guarded.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./resolvers/ENSPubKeyResolver.sol\";\nimport \"./resolvers/ENSTextResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n\n/**\n * @title ENS controller\n *\n * @notice ENS subnode registrar\n *\n * @dev The process of adding root node consists of 3 steps:\n * 1. `submitNode` - should be called from ENS node owner,\n * 2. Change ENS node owner in ENS registry to ENS controller,\n * 3. `verifyNode` - should be called from previous ENS node owner,\n *\n * To register sub node, `msg.sender` need to send valid signature from one of guardian key.\n * Once registration is complete `msg.sender` becoming both node owner and `addr` record value.\n *\n * After registration sub node cannot be replaced.\n *\n * @author Stanisław Głogowski \n */\ncontract ENSController is Guarded, Initializable, SignatureValidator, GatewayRecipient, ENSAddressResolver, ENSNameResolver, ENSPubKeyResolver, ENSTextResolver {\n struct SubNodeRegistration {\n address account;\n bytes32 node;\n bytes32 label;\n }\n\n bytes4 private constant INTERFACE_META_ID = bytes4(keccak256(abi.encodePacked(\"supportsInterface(bytes4)\")));\n\n bytes32 private constant HASH_PREFIX_SUB_NODE_REGISTRATION = keccak256(\n \"SubNodeRegistration(address account,bytes32 node,bytes32 label)\"\n );\n\n ENSRegistry public registry;\n\n mapping(bytes32 => address) public nodeOwners;\n\n // events\n\n /**\n * @dev Emitted when new node is submitted\n * @param node node name hash\n * @param owner owner address\n */\n event NodeSubmitted(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when the existing owner is verified\n * @param node node name hash\n */\n event NodeVerified(\n bytes32 node\n );\n\n /**\n * @dev Emitted when new node is released\n * @param node node name hash\n * @param owner owner address\n */\n event NodeReleased(\n bytes32 node,\n address owner\n );\n\n /**\n * @dev Emitted when ENS registry address is changed\n * @param registry registry address\n */\n event RegistryChanged(\n address registry\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Guarded() Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSController` contract\n * @param registry_ ENS registry address\n * @param gateway_ gateway address\n */\n function initialize(\n ENSRegistry registry_,\n address[] calldata guardians_,\n address gateway_\n )\n external\n onlyInitializer\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n registry = registry_;\n\n // Guarded\n _initializeGuarded(guardians_);\n\n // GatewayRecipient\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Sets registry\n * @param registry_ registry address\n */\n function setRegistry(\n ENSRegistry registry_\n )\n external\n onlyGuardian\n {\n require(\n address(registry_) != address(0),\n \"ENSController: cannot set 0x0 registry\"\n );\n\n require(\n registry_ != registry,\n \"ENSController: registry already set\"\n );\n\n registry = registry_;\n\n emit RegistryChanged(\n address(registry)\n );\n }\n\n /**\n * @notice Submits node\n * @dev Should be called from the current ENS node owner\n * @param node node name hash\n */\n function submitNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == address(0),\n \"ENSController: node already submitted\"\n );\n\n require(\n registry.owner(node) == owner,\n \"ENSController: invalid ens node owner\"\n );\n\n nodeOwners[node] = owner;\n\n emit NodeSubmitted(node, owner);\n }\n\n /**\n * @notice Verifies node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function verifyNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already exists\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n require(\n registry.owner(node) == address(this),\n \"ENSController: invalid ens node owner\"\n );\n\n _setAddr(node, address(this));\n\n registry.setResolver(node, address(this));\n\n emit NodeVerified(node);\n }\n\n /**\n * @notice Releases node\n * @dev Should be called from the previous ENS node owner\n * @param node node name hash\n */\n function releaseNode(\n bytes32 node\n )\n external\n {\n address owner = _getContextAccount();\n\n require(\n _addr(node) == address(this),\n \"ENSController: node doesn't exist\"\n );\n\n require(\n nodeOwners[node] == owner,\n \"ENSController: invalid node owner\"\n );\n\n registry.setOwner(node, owner);\n\n delete nodeOwners[node];\n\n emit NodeReleased(node, owner);\n }\n\n /**\n * @notice Sync address\n * @param node node name hash\n */\n function syncAddr(\n bytes32 node\n )\n external\n {\n address account = _getContextAccount();\n\n require(\n account == registry.owner(node),\n \"ENSController: caller is not the node owner\"\n );\n\n require(\n registry.resolver(node) == address(this),\n \"ENSController: invalid node resolver\"\n );\n\n require(\n _addr(node) == address(0),\n \"ENSController: node already in sync\"\n );\n\n _setAddr(node, account);\n }\n\n /**\n * @notice Registers sub node\n * @param node node name hash\n * @param label label hash\n * @param guardianSignature guardian signature\n */\n function registerSubNode(\n bytes32 node,\n bytes32 label,\n bytes calldata guardianSignature\n )\n external\n {\n address account = _getContextAccount();\n\n bytes32 messageHash = _hashSubNodeRegistration(\n account,\n node,\n label\n );\n\n require(\n _verifyGuardianSignature(messageHash, guardianSignature),\n \"ENSController: invalid guardian signature\"\n );\n\n bytes32 subNode = keccak256(\n abi.encodePacked(\n node,\n label\n )\n );\n\n require(\n _addr(node) == address(this),\n \"ENSController: invalid node\"\n );\n\n require(\n _addr(subNode) == address(0),\n \"ENSController: label already taken\"\n );\n\n registry.setSubnodeRecord(node, label, address(this), address(this), 0);\n registry.setOwner(subNode, account);\n\n _setAddr(subNode, account);\n }\n\n // external functions (pure)\n function supportsInterface(\n bytes4 interfaceID\n )\n external\n pure\n returns(bool)\n {\n return interfaceID == INTERFACE_META_ID ||\n interfaceID == INTERFACE_ADDR_ID ||\n interfaceID == INTERFACE_ADDRESS_ID ||\n interfaceID == INTERFACE_NAME_ID ||\n interfaceID == INTERFACE_PUB_KEY_ID ||\n interfaceID == INTERFACE_TEXT_ID;\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `SubNodeRegistration` message payload\n * @param subNodeRegistration struct\n * @return hash\n */\n function hashSubNodeRegistration(\n SubNodeRegistration memory subNodeRegistration\n )\n public\n view\n returns (bytes32)\n {\n return _hashSubNodeRegistration(\n subNodeRegistration.account,\n subNodeRegistration.node,\n subNodeRegistration.label\n );\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n override\n view\n returns (bool)\n {\n return registry.owner(node) == _getContextAccount();\n }\n\n // private functions (views)\n\n function _hashSubNodeRegistration(\n address account,\n bytes32 node,\n bytes32 label\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_SUB_NODE_REGISTRATION, abi.encodePacked(\n account,\n node,\n label\n ));\n }\n}\n" + }, + "src/ens/resolvers/ENSAddressResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract address resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/AddrResolver.sol\n */\nabstract contract ENSAddressResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_ADDR_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32)\")));\n bytes4 internal constant INTERFACE_ADDRESS_ID = bytes4(keccak256(abi.encodePacked(\"addr(bytes32,uint)\")));\n\n uint internal constant COIN_TYPE_ETH = 60;\n\n mapping(bytes32 => mapping(uint => bytes)) internal resolverAddresses;\n\n // events\n\n event AddrChanged(\n bytes32 indexed node,\n address addr\n );\n\n event AddressChanged(\n bytes32 indexed node,\n uint coinType,\n bytes newAddress\n );\n\n // external functions\n\n function setAddr(\n bytes32 node,\n address addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, addr_);\n }\n\n function setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n external\n onlyNodeOwner(node)\n {\n _setAddr(node, coinType, addr_);\n }\n\n // external functions (views)\n\n function addr(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return _addr(node);\n }\n\n function addr(\n bytes32 node,\n uint coinType\n )\n external\n view\n returns (bytes memory)\n {\n return resolverAddresses[node][coinType];\n }\n\n // internal functions\n\n function _setAddr(\n bytes32 node,\n address addr_\n )\n internal\n {\n _setAddr(node, COIN_TYPE_ETH, _addressToBytes(addr_));\n }\n\n function _setAddr(\n bytes32 node,\n uint coinType,\n bytes memory addr_\n )\n internal\n {\n emit AddressChanged(node, coinType, addr_);\n\n if(coinType == COIN_TYPE_ETH) {\n emit AddrChanged(node, _bytesToAddress(addr_));\n }\n\n resolverAddresses[node][coinType] = addr_;\n }\n\n // internal functions (views)\n\n function _addr(\n bytes32 node\n )\n internal\n view\n returns (address)\n {\n address result;\n\n bytes memory addr_ = resolverAddresses[node][COIN_TYPE_ETH];\n\n if (addr_.length > 0) {\n result = _bytesToAddress(addr_);\n }\n\n return result;\n }\n\n // private function (pure)\n\n function _bytesToAddress(\n bytes memory data\n )\n private\n pure\n returns(address payable)\n {\n address payable result;\n\n require(data.length == 20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 32)), exp(256, 12))\n }\n\n return result;\n }\n\n function _addressToBytes(\n address addr_\n )\n private\n pure\n returns(bytes memory)\n {\n bytes memory result = new bytes(20);\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(add(result, 32), mul(addr_, exp(256, 12)))\n }\n\n return result;\n }\n}\n" + }, + "src/ens/resolvers/ENSNameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract name resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/NameResolver.sol\n */\nabstract contract ENSNameResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_NAME_ID = bytes4(keccak256(abi.encodePacked(\"name(bytes32)\")));\n\n mapping(bytes32 => string) internal resolverNames;\n\n // events\n\n event NameChanged(\n bytes32 indexed node,\n string name\n );\n\n // external functions\n\n function setName(\n bytes32 node,\n string calldata name\n )\n external\n onlyNodeOwner(node)\n {\n resolverNames[node] = name;\n\n emit NameChanged(node, name);\n }\n\n // external functions (views)\n\n function name(\n bytes32 node\n )\n external\n view\n returns (string memory)\n {\n return resolverNames[node];\n }\n}\n" + }, + "src/ens/resolvers/ENSPubKeyResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract pub key resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/PubkeyResolver.sol\n */\nabstract contract ENSPubKeyResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_PUB_KEY_ID = bytes4(keccak256(abi.encodePacked(\"pubkey(bytes32)\")));\n\n struct PubKey {\n bytes32 x;\n bytes32 y;\n }\n\n mapping(bytes32 => PubKey) internal resolverPubKeys;\n\n // events\n\n event PubkeyChanged(\n bytes32 indexed node,\n bytes32 x,\n bytes32 y\n );\n\n // external functions (views)\n\n function setPubkey(\n bytes32 node,\n bytes32 x,\n bytes32 y\n )\n external\n onlyNodeOwner(node)\n {\n resolverPubKeys[node] = PubKey(x, y);\n\n emit PubkeyChanged(node, x, y);\n }\n\n // external functions (views)\n\n function pubkey(\n bytes32 node\n )\n external\n view\n returns (bytes32 x, bytes32 y)\n {\n return (resolverPubKeys[node].x, resolverPubKeys[node].y);\n }\n}\n" + }, + "src/ens/resolvers/ENSTextResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"./ENSAbstractResolver.sol\";\n\n\n/**\n * @title ENS abstract text resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/profiles/TextResolver.sol\n */\nabstract contract ENSTextResolver is ENSAbstractResolver {\n bytes4 internal constant INTERFACE_TEXT_ID = bytes4(keccak256(abi.encodePacked(\"text(bytes32,string)\")));\n\n mapping(bytes32 => mapping(string => string)) internal resolverTexts;\n\n // events\n\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key\n );\n\n // external functions (views)\n\n function setText(\n bytes32 node,\n string calldata key,\n string calldata value\n )\n external\n onlyNodeOwner(node)\n {\n resolverTexts[node][key] = value;\n\n emit TextChanged(node, key, key);\n }\n\n // external functions (views)\n\n function text(\n bytes32 node,\n string calldata key\n )\n external\n view\n returns (string memory)\n {\n return resolverTexts[node][key];\n }\n}\n" + }, + "src/ens/ENSRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS registry\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\n */\ncontract ENSRegistry {\n struct Record {\n address owner;\n address resolver;\n uint64 ttl;\n }\n\n mapping (bytes32 => Record) private records;\n mapping (address => mapping(address => bool)) private operators;\n\n // events\n\n event NewOwner(\n bytes32 indexed node,\n bytes32 indexed label,\n address owner\n );\n\n event Transfer(\n bytes32 indexed node,\n address owner\n );\n\n event NewResolver(\n bytes32 indexed node,\n address resolver\n );\n\n event NewTTL(\n bytes32 indexed node,\n uint64 ttl\n );\n\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n // modifiers\n\n modifier authorised(\n bytes32 node\n )\n {\n address owner = records[node].owner;\n\n require(\n owner == msg.sender || operators[owner][msg.sender],\n \"ENSRegistry: reverted by authorised modifier\"\n );\n\n _;\n }\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n {\n // solhint-disable-next-line avoid-tx-origin\n records[0x0].owner = tx.origin;\n }\n\n // external functions\n\n function setRecord(\n bytes32 node,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n setOwner(node, owner_);\n\n _setResolverAndTTL(node, resolver_, ttl_);\n }\n\n function setTTL(\n bytes32 node,\n uint64 ttl_\n )\n external\n authorised(node)\n {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner_,\n address resolver_,\n uint64 ttl_\n )\n external\n {\n bytes32 subNode = setSubnodeOwner(node, label, owner_);\n\n _setResolverAndTTL(subNode, resolver_, ttl_);\n }\n\n function setApprovalForAll(\n address operator,\n bool approved\n )\n external\n {\n operators[msg.sender][operator] = approved;\n\n emit ApprovalForAll(\n msg.sender,\n operator,\n approved\n );\n }\n\n // external functions (views)\n\n function owner(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n address addr = records[node].owner;\n\n if (addr == address(this)) {\n return address(0x0);\n }\n\n return addr;\n }\n\n function resolver(\n bytes32 node\n )\n external\n view\n returns (address)\n {\n return records[node].resolver;\n }\n\n function ttl(\n bytes32 node\n )\n external\n view\n returns (uint64)\n {\n return records[node].ttl;\n }\n\n function recordExists(\n bytes32 node\n )\n external\n view\n returns (bool)\n {\n return records[node].owner != address(0x0);\n }\n\n function isApprovedForAll(\n address owner_,\n address operator\n )\n external\n view\n returns (bool)\n {\n return operators[owner_][operator];\n }\n\n // public functions\n\n function setOwner(\n bytes32 node,\n address owner_\n )\n public\n authorised(node)\n {\n records[node].owner = owner_;\n\n emit Transfer(node, owner_);\n }\n\n function setResolver(\n bytes32 node,\n address resolver_\n )\n public\n authorised(node)\n {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner_\n )\n public\n authorised(node)\n returns(bytes32)\n {\n bytes32 subNode = keccak256(abi.encodePacked(node, label));\n\n records[subNode].owner = owner_;\n\n emit NewOwner(node, label, owner_);\n\n return subNode;\n }\n\n // private functions\n\n function _setResolverAndTTL(\n bytes32 node,\n address resolver_,\n uint64 ttl_\n )\n private\n {\n if (resolver_ != records[node].resolver) {\n records[node].resolver = resolver_;\n\n emit NewResolver(node, resolver_);\n }\n\n if (ttl_ != records[node].ttl) {\n records[node].ttl = ttl_;\n\n emit NewTTL(node, ttl_);\n }\n }\n}\n" + }, + "src/ens/resolvers/ENSAbstractResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title ENS abstract resolver\n *\n * @dev Base on https://github.com/ensdomains/resolvers/blob/f7d62ab04bfe1692a4344f6f1d31ff81315a98c3/contracts/ResolverBase.sol\n */\nabstract contract ENSAbstractResolver {\n // modifiers\n\n modifier onlyNodeOwner(bytes32 node)\n {\n require(\n _isNodeOwner(node),\n \"ENSAbstractResolver: reverted by onlyNodeOwner modifier\"\n );\n\n _;\n }\n\n // internal functions (views)\n\n function _isNodeOwner(\n bytes32 node\n )\n internal\n virtual\n view\n returns (bool);\n}\n" + }, + "src/ens/ENSReverseRegistrar.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/AddressLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS reverse registrar\n *\n * @dev Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\n */\ncontract ENSReverseRegistrar is Initializable {\n using AddressLib for address;\n\n // namehash('addr.reverse')\n bytes32 public constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n ENSRegistry public registry;\n ENSNameResolver public resolver;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSReverseRegistrar` contract\n * @param registry_ ENS registry address\n * @param resolver_ ENS name resolver address\n */\n function initialize(\n ENSRegistry registry_,\n ENSNameResolver resolver_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n resolver = resolver_;\n }\n\n // external functions\n\n function claim(\n address owner\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, address(0));\n }\n\n function claimWithResolver(\n address owner,\n address resolver_\n )\n public\n returns (bytes32)\n {\n return _claimWithResolver(owner, resolver_);\n }\n\n function setName(\n string memory name\n )\n public\n returns (bytes32)\n {\n bytes32 node = _claimWithResolver(address(this), address(resolver));\n\n resolver.setName(node, name);\n\n return node;\n }\n\n // external functions (pure)\n\n function node(\n address addr_\n )\n external\n pure\n returns (bytes32)\n {\n return keccak256(abi.encodePacked(ADDR_REVERSE_NODE, addr_.toSha3Hash()));\n }\n\n // private functions\n\n function _claimWithResolver(\n address owner,\n address resolver_\n )\n private\n returns (bytes32)\n {\n bytes32 label = address(msg.sender).toSha3Hash();\n bytes32 node_ = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n address currentOwner = registry.owner(node_);\n\n if (resolver_ != address(0x0) && resolver_ != registry.resolver(node_)) {\n if (currentOwner != address(this)) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this));\n currentOwner = address(this);\n }\n\n registry.setResolver(node_, resolver_);\n }\n\n // Update the owner if required\n if (currentOwner != owner) {\n registry.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);\n }\n\n return node_;\n }\n}\n" + }, + "src/common/libs/AddressLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Address library\n */\nlibrary AddressLib {\n /**\n * @notice Converts address into sha3 hash\n * @param self address\n * @return sha3 hash\n */\n function toSha3Hash(\n address self\n )\n internal\n pure\n returns (bytes32)\n {\n bytes32 result;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000\n\n for { let i := 40 } gt(i, 0) { } {\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(self, 0xf), lookup))\n self := div(self, 0x10)\n }\n\n result := keccak256(0, 40)\n }\n\n return result;\n }\n}\n" + }, + "src/ens/ENSHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"./resolvers/ENSAddressResolver.sol\";\nimport \"./resolvers/ENSNameResolver.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * @title ENS helper\n *\n * @author Stanisław Głogowski \n */\ncontract ENSHelper is Initializable {\n ENSRegistry public registry;\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `ENSLookupHelper` contract\n * @param registry_ ENS registry address\n */\n function initialize(\n ENSRegistry registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n /**\n * @notice Gets nodes addresses\n * @param nodes array of nodes\n * @return nodes addresses\n */\n function getAddresses(\n bytes32[] memory nodes\n )\n external\n view\n returns (address[] memory)\n {\n uint nodesLen = nodes.length;\n address[] memory result = new address[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getAddress(nodes[i]);\n }\n\n return result;\n }\n\n /**\n * @notice Gets nodes names\n * @param nodes array of nodes\n * @return nodes names\n */\n function getNames(\n bytes32[] memory nodes\n )\n external\n view\n returns (string[] memory)\n {\n uint nodesLen = nodes.length;\n string[] memory result = new string[](nodesLen);\n\n for (uint i = 0; i < nodesLen; i++) {\n result[i] = _getName(nodes[i]);\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getAddress(\n bytes32 node\n )\n private\n view\n returns (address)\n {\n address result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSAddressResolver(resolver).addr(node) returns (address addr) {\n result = addr;\n } catch {\n //\n }\n }\n\n return result;\n }\n\n function _getName(\n bytes32 node\n )\n private\n view\n returns (string memory)\n {\n string memory result;\n address resolver = registry.resolver(node);\n\n if (resolver != address(0)) {\n try ENSNameResolver(resolver).name(node) returns (string memory name) {\n result = name;\n } catch {\n //\n }\n }\n\n return result;\n }\n}\n" + }, + "src/common/account/AccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../lifecycle/Initializable.sol\";\nimport \"./AccountBase.sol\";\nimport \"./AccountRegistry.sol\";\n\n\n/**\n * @title Account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1 is Initializable, AccountBase {\n bytes32 constant private ERC777_TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(abi.encodePacked(\"ERC777TokensRecipient\"));\n bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n bytes4 constant private ERC1271_VALID_MESSAGE_HASH_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes32,bytes)\")));\n bytes4 constant private ERC1271_VALID_MESSAGE_SIGNATURE = bytes4(keccak256(abi.encodePacked(\"isValidSignature(bytes,bytes)\")));\n bytes4 constant private ERC1271_INVALID_SIGNATURE = 0xffffffff;\n\n /**\n * @dev Internal constructor\n */\n constructor() internal Initializable() {}\n\n // external functions\n\n /**\n * @notice Initializes `AccountImplementation` contract\n * @param registry_ registry address\n */\n function initialize(\n address registry_\n )\n external\n onlyInitializer\n {\n registry = registry_;\n }\n\n // external functions (views)\n\n // ERC1820\n\n function canImplementInterfaceForAddress(\n bytes32 interfaceHash,\n address addr\n )\n external\n view\n returns(bytes32)\n {\n bytes32 result;\n\n if (interfaceHash == ERC777_TOKENS_RECIPIENT_INTERFACE_HASH && addr == address(this)) {\n result = ERC1820_ACCEPT_MAGIC;\n }\n\n return result;\n }\n\n // ERC1271\n\n function isValidSignature(\n bytes32 messageHash,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), messageHash, signature)\n ? ERC1271_VALID_MESSAGE_HASH_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n function isValidSignature(\n bytes calldata message,\n bytes calldata signature\n )\n external\n view\n returns (bytes4)\n {\n return AccountRegistry(registry).isValidAccountSignature(address(this), message, signature)\n ? ERC1271_VALID_MESSAGE_SIGNATURE\n : ERC1271_INVALID_SIGNATURE;\n }\n\n // external functions (pure)\n\n // ERC721\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC721Received.selector;\n }\n\n // ERC1155\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n )\n external\n pure\n returns (bytes4)\n {\n return this.onERC1155Received.selector;\n }\n\n // ERC777\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n )\n external\n pure\n {}\n}\n" + }, + "src/personal/PersonalAccountImplementationV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/account/AccountImplementationV1.sol\";\n\n\n/**\n * @title Personal account implementation (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\n\n /**\n * @dev Public constructor\n */\n constructor() public AccountImplementationV1() {}\n}\n" + }, + "src/common/account/mocks/AccountImplementationV1Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountImplementationV1.sol\";\n\n\n/**\n * @title Account implementation mock (version 1)\n *\n * @author Stanisław Głogowski \n */\ncontract AccountImplementationV1Mock is AccountImplementationV1 {\n /**\n * @dev Public constructor\n * @param registry_ account registry address\n */\n constructor(\n address registry_\n )\n public\n AccountImplementationV1()\n {\n registry = registry_;\n }\n}\n" + } + }, + "settings": { + "evmVersion": "istanbul", + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/dist/constants.d.ts b/dist/constants.d.ts index 7e4fbd4d..3230e51b 100644 --- a/dist/constants.d.ts +++ b/dist/constants.d.ts @@ -34,6 +34,7 @@ export declare enum ContractNames { ExternalAccountRegistry = 'ExternalAccountRegistry', Gateway = 'Gateway', GatewayRecipient = 'GatewayRecipient', + GatewayV2 = 'GatewayV2', Guarded = 'Guarded', Home = 'Home', HopFacet = 'HopFacet', @@ -101,4 +102,5 @@ export declare enum ContractNames { WrappedWeiToken = 'WrappedWeiToken', XAppConnectionClient = 'XAppConnectionClient', XAppConnectionManager = 'XAppConnectionManager', + console = 'console', } diff --git a/dist/constants.js b/dist/constants.js index 65e63c6c..52a4d700 100644 --- a/dist/constants.js +++ b/dist/constants.js @@ -37,6 +37,7 @@ module.exports = { ExternalAccountRegistry: 'ExternalAccountRegistry', Gateway: 'Gateway', GatewayRecipient: 'GatewayRecipient', + GatewayV2: 'GatewayV2', Guarded: 'Guarded', Home: 'Home', HopFacet: 'HopFacet', @@ -104,5 +105,6 @@ module.exports = { WrappedWeiToken: 'WrappedWeiToken', XAppConnectionClient: 'XAppConnectionClient', XAppConnectionManager: 'XAppConnectionManager', + console: 'console', }, }; diff --git a/dist/contracts.js b/dist/contracts.js index fd9d65e2..a9d1ddf5 100644 --- a/dist/contracts.js +++ b/dist/contracts.js @@ -1085,8 +1085,8 @@ module.exports = { "42": null, "56": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "69": null, - "77": null, - "97": null, + "77": "0xe5A160F89f330cc933816E896a3F36376DE0a835", + "97": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "100": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "122": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "123": "0xe5A160F89f330cc933816E896a3F36376DE0a835", @@ -1101,11 +1101,11 @@ module.exports = { "42161": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "42170": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "42220": "0xe5A160F89f330cc933816E896a3F36376DE0a835", - "43113": null, + "43113": "0x13261B2b8674Cb855c408F3721281330ee16C66E", "43114": "0x13261B2b8674Cb855c408F3721281330ee16C66E", "44787": null, "80001": "0xe5A160F89f330cc933816E896a3F36376DE0a835", - "421611": null, + "421611": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "421613": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "1313161554": "0xe5A160F89f330cc933816E896a3F36376DE0a835", "1313161555": "0xe5A160F89f330cc933816E896a3F36376DE0a835" @@ -5482,51 +5482,603 @@ module.exports = { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "batch", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bool", + "name": "succeeded", + "type": "bool" + } + ], + "name": "BatchDelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "initializer", + "type": "address" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [], + "name": "chainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "to", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "senderSignature", + "type": "bytes" + } + ], + "name": "delegateBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "to", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "senderSignature", + "type": "bytes" + } + ], + "name": "delegateBatchWithGasPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "batches", + "type": "bytes[]" + }, + { + "internalType": "bool", + "name": "revertOnFailure", + "type": "bool" + } + ], + "name": "delegateBatches", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "externalAccountRegistry", + "outputs": [ + { + "internalType": "contract ExternalAccountRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountNextNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "to", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "internalType": "struct Gateway.DelegatedBatch", + "name": "delegatedBatch", + "type": "tuple" + } + ], + "name": "hashDelegatedBatch", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "to", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + } + ], + "internalType": "struct Gateway.DelegatedBatchWithGasPrice", + "name": "delegatedBatch", + "type": "tuple" + } + ], + "name": "hashDelegatedBatchWithGasPrice", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ExternalAccountRegistry", + "name": "externalAccountRegistry_", + "type": "address" + }, + { + "internalType": "contract PersonalAccountRegistry", + "name": "personalAccountRegistry_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "personalAccountRegistry", + "outputs": [ + { + "internalType": "contract PersonalAccountRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "to", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "sendBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "to", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "sendBatchFromAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "addresses": { + "1": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "3": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "4": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "5": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "10": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "42": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "56": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "69": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "77": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "97": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "100": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "122": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "123": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "137": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "250": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "1284": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "1287": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "3333": null, + "4002": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "4386": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "6666": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "42161": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "42170": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "42220": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "43113": "0xf96E0A8e408604F2c45e13c89bB395815BD5Efc6", + "43114": "0xf96E0A8e408604F2c45e13c89bB395815BD5Efc6", + "44787": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "80001": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "421611": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "421613": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "1313161554": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", + "1313161555": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163" + }, + "byteCode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600046905080600181905550506123f58061006d6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063867519c61161008c5780639f255626116100665780639f255626146101fe578063b5021b161461021a578063d2c83b9a14610236578063f92c5f7c14610254576100cf565b8063867519c6146101a657806387d31313146101c25780639a8a0592146101e0576100cf565b8063231badaf146100d4578063392e53cd146100f0578063485cc9551461010e5780635afaa7bb1461012a57806373e5a13f1461014657806376db2b4c14610176575b600080fd5b6100ee60048036038101906100e99190611438565b610284565b005b6100f861037f565b6040516101059190611e71565b60405180910390f35b610128600480360381019061012391906115e0565b6103d5565b005b610144600480360381019061013f9190611563565b610561565b005b610160600480360381019061015b919061165d565b610739565b60405161016d9190611e8c565b60405180910390f35b610190600480360381019061018b919061161c565b61075e565b60405161019d9190611e8c565b60405180910390f35b6101c060048036038101906101bb91906113b9565b610788565b005b6101ca610799565b6040516101d79190611f07565b60405180910390f35b6101e86107bf565b6040516101f591906120a2565b60405180910390f35b610218600480360381019061021391906114f7565b6107c5565b005b610234600480360381019061022f9190611438565b6107d5565b005b61023e6108d1565b60405161024b9190611eec565b60405180910390f35b61026e60048036038101906102699190611390565b6108f7565b60405161027b91906120a2565b60405180910390f35b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fc90611f82565b60405180910390fd5b60006103258261031788888888610953565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061037786828686610a71565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045a90611f42565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516105559190611def565b60405180910390a15050565b60008251116105a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059c90611fc2565b60405180910390fd5b600080600090505b83518110156106f35760003073ffffffffffffffffffffffffffffffffffffffff168583815181106105db57fe5b60200260200101516040516105f09190611d0b565b6000604051808303816000865af19150503d806000811461062d576040519150601f19603f3d011682016040523d82523d6000602084013e610632565b606091505b505090508315610681578061067c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067390611f62565b60405180910390fd5b610697565b80801561068c575082155b1561069657600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106106c557fe5b6020026020010151836040516106dd93929190611e0a565b60405180910390a15080806001019150506105ad565b5080610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072b90612082565b60405180910390fd5b505050565b60006107578260000151836020015184604001518560600151610953565b9050919050565b600061078182600001518360200151846040015185606001518660800151610edc565b9050919050565b61079483338484610a71565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b6107d133338484610a71565b5050565b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084d90611f82565b60405180910390fd5b600061087782610869888888883a610edc565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108c986828686610a71565b505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061094c6001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f4290919063ffffffff16565b9050919050565b60006109ac7f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661098587610f97565b6040516020016109989493929190611c6e565b604051602081830303815290604052610ffa565b9050949350505050565b60008060009050604183511415610a675760008060006020860151925060408601519150606086015160001a9050601b8160ff1610156109f757601b810190505b601b8160ff161480610a0c5750601c8160ff16145b15610a635760018782858560405160008152602001604052604051610a349493929190611ea7565b6020604051602081039080840390855afa158015610a56573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415610ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad890611fa2565b60405180910390fd5b6000825111610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c90612062565b60405180910390fd5b8151815114610b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6090612002565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610d3d57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610bf9929190611e48565b60206040518083038186803b158015610c1157600080fd5b505afa158015610c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4991906115b7565b80610cfd5750600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610cac929190611e48565b60206040518083038186803b158015610cc457600080fd5b505afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc91906115b7565b5b610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3390611fe2565b60405180910390fd5b5b600080600090505b8251811015610ed457600073ffffffffffffffffffffffffffffffffffffffff16848281518110610d7257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff161415610dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc890611f22565b60405180910390fd5b838181518110610ddd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16838281518110610e0757fe5b60200260200101518787604051602001610e2393929190611d22565b604051602081830303815290604052604051610e3f9190611d0b565b6000604051808303816000865af19150503d8060008114610e7c576040519150601f19603f3d011682016040523d82523d6000602084013e610e81565b606091505b50508092505081610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebe90612022565b60405180910390fd5b8080600101915050610d45565b505050505050565b6000610f377f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad878787610f0e88610f97565b87604051602001610f23959493929190611cb4565b604051602081830303815290604052610ffa565b905095945050505050565b600080828401905083811015610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490612042565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015610fef5782858281518110610fb857fe5b6020026020010151604051602001610fd1929190611d5b565b60405160208183030381529060405292508080600101915050610fa3565b508192505050919050565b60006110336001543085856040516020016110189493929190611da5565b6040516020818303038152906040528051906020012061103b565b905092915050565b60008160405160200161104e9190611d7f565b604051602081830303815290604052805190602001209050919050565b60008135905061107a81612375565b92915050565b600082601f83011261109157600080fd5b81356110a461109f826120ea565b6120bd565b915081818352602084019350602081019050838560208402820111156110c957600080fd5b60005b838110156110f957816110df888261106b565b8452602084019350602083019250506001810190506110cc565b5050505092915050565b600082601f83011261111457600080fd5b813561112761112282612112565b6120bd565b9150818183526020840193506020810190508360005b8381101561116d578135860161115388826111a1565b84526020840193506020830192505060018101905061113d565b5050505092915050565b6000813590506111868161238c565b92915050565b60008151905061119b8161238c565b92915050565b600082601f8301126111b257600080fd5b81356111c56111c08261213a565b6120bd565b915080825260208301602083018583830111156111e157600080fd5b6111ec8382846122dd565b50505092915050565b600081359050611204816123a3565b92915050565b600081359050611219816123ba565b92915050565b600060a0828403121561123157600080fd5b61123b60a06120bd565b9050600061124b8482850161106b565b600083015250602061125f8482850161137b565b602083015250604082013567ffffffffffffffff81111561127f57600080fd5b61128b84828501611080565b604083015250606082013567ffffffffffffffff8111156112ab57600080fd5b6112b784828501611103565b60608301525060806112cb8482850161137b565b60808301525092915050565b6000608082840312156112e957600080fd5b6112f360806120bd565b905060006113038482850161106b565b60008301525060206113178482850161137b565b602083015250604082013567ffffffffffffffff81111561133757600080fd5b61134384828501611080565b604083015250606082013567ffffffffffffffff81111561136357600080fd5b61136f84828501611103565b60608301525092915050565b60008135905061138a816123d1565b92915050565b6000602082840312156113a257600080fd5b60006113b08482850161106b565b91505092915050565b6000806000606084860312156113ce57600080fd5b60006113dc8682870161106b565b935050602084013567ffffffffffffffff8111156113f957600080fd5b61140586828701611080565b925050604084013567ffffffffffffffff81111561142257600080fd5b61142e86828701611103565b9150509250925092565b600080600080600060a0868803121561145057600080fd5b600061145e8882890161106b565b955050602061146f8882890161137b565b945050604086013567ffffffffffffffff81111561148c57600080fd5b61149888828901611080565b935050606086013567ffffffffffffffff8111156114b557600080fd5b6114c188828901611103565b925050608086013567ffffffffffffffff8111156114de57600080fd5b6114ea888289016111a1565b9150509295509295909350565b6000806040838503121561150a57600080fd5b600083013567ffffffffffffffff81111561152457600080fd5b61153085828601611080565b925050602083013567ffffffffffffffff81111561154d57600080fd5b61155985828601611103565b9150509250929050565b6000806040838503121561157657600080fd5b600083013567ffffffffffffffff81111561159057600080fd5b61159c85828601611103565b92505060206115ad85828601611177565b9150509250929050565b6000602082840312156115c957600080fd5b60006115d78482850161118c565b91505092915050565b600080604083850312156115f357600080fd5b6000611601858286016111f5565b92505060206116128582860161120a565b9150509250929050565b60006020828403121561162e57600080fd5b600082013567ffffffffffffffff81111561164857600080fd5b6116548482850161121f565b91505092915050565b60006020828403121561166f57600080fd5b600082013567ffffffffffffffff81111561168957600080fd5b611695848285016112d7565b91505092915050565b60006116aa83836116d4565b60208301905092915050565b6116bf8161225f565b82525050565b6116ce816121dc565b82525050565b6116dd816121dc565b82525050565b6116f46116ef826121dc565b61231f565b82525050565b600061170582612176565b61170f8185612199565b935061171a83612166565b8060005b8381101561174b578151611732888261169e565b975061173d8361218c565b92505060018101905061171e565b5085935050505092915050565b611761816121ee565b82525050565b611770816121fa565b82525050565b611787611782826121fa565b612331565b82525050565b600061179882612181565b6117a281856121a4565b93506117b28185602086016122ec565b6117bb81612357565b840191505092915050565b60006117d182612181565b6117db81856121b5565b93506117eb8185602086016122ec565b80840191505092915050565b61180081612271565b82525050565b61180f81612295565b82525050565b6000611822601b836121c0565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000611862601c836121d1565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006118a2602f836121c0565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006119086017836121c0565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006119486032836121c0565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b60006119ae6025836121c0565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a146026836121c0565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a7a6028836121c0565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ae06016836121c0565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000611b206023836121c0565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611b86601e836121c0565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000611bc66020836121c0565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b6000611c06601d836121c0565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b611c4281612248565b82525050565b611c59611c5482612248565b61234d565b82525050565b611c6881612252565b82525050565b6000611c7a82876116e3565b601482019150611c8a8286611c48565b602082019150611c9a82856116fa565b9150611ca682846117c6565b915081905095945050505050565b6000611cc082886116e3565b601482019150611cd08287611c48565b602082019150611ce082866116fa565b9150611cec82856117c6565b9150611cf88284611c48565b6020820191508190509695505050505050565b6000611d1782846117c6565b915081905092915050565b6000611d2e82866117c6565b9150611d3a82856116e3565b601482019150611d4a82846116e3565b601482019150819050949350505050565b6000611d6782856117c6565b9150611d7382846117c6565b91508190509392505050565b6000611d8a82611855565b9150611d968284611776565b60208201915081905092915050565b6000611db18287611c48565b602082019150611dc182866116e3565b601482019150611dd18285611776565b602082019150611de182846117c6565b915081905095945050505050565b6000602082019050611e0460008301846116b6565b92915050565b6000606082019050611e1f60008301866116b6565b8181036020830152611e31818561178d565b9050611e406040830184611758565b949350505050565b6000604082019050611e5d60008301856116c5565b611e6a60208301846116c5565b9392505050565b6000602082019050611e866000830184611758565b92915050565b6000602082019050611ea16000830184611767565b92915050565b6000608082019050611ebc6000830187611767565b611ec96020830186611c5f565b611ed66040830185611767565b611ee36060830184611767565b95945050505050565b6000602082019050611f0160008301846117f7565b92915050565b6000602082019050611f1c6000830184611806565b92915050565b60006020820190508181036000830152611f3b81611815565b9050919050565b60006020820190508181036000830152611f5b81611895565b9050919050565b60006020820190508181036000830152611f7b816118fb565b9050919050565b60006020820190508181036000830152611f9b8161193b565b9050919050565b60006020820190508181036000830152611fbb816119a1565b9050919050565b60006020820190508181036000830152611fdb81611a07565b9050919050565b60006020820190508181036000830152611ffb81611a6d565b9050919050565b6000602082019050818103600083015261201b81611ad3565b9050919050565b6000602082019050818103600083015261203b81611b13565b9050919050565b6000602082019050818103600083015261205b81611b79565b9050919050565b6000602082019050818103600083015261207b81611bb9565b9050919050565b6000602082019050818103600083015261209b81611bf9565b9050919050565b60006020820190506120b76000830184611c39565b92915050565b6000604051905081810181811067ffffffffffffffff821117156120e057600080fd5b8060405250919050565b600067ffffffffffffffff82111561210157600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561212957600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561215157600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006121e782612228565b9050919050565b60008115159050919050565b6000819050919050565b600061220f826121dc565b9050919050565b6000612221826121dc565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061226a826122b9565b9050919050565b600061227c82612283565b9050919050565b600061228e82612228565b9050919050565b60006122a0826122a7565b9050919050565b60006122b282612228565b9050919050565b60006122c4826122cb565b9050919050565b60006122d682612228565b9050919050565b82818337600083830152505050565b60005b8381101561230a5780820151818401526020810190506122ef565b83811115612319576000848401525b50505050565b600061232a8261233b565b9050919050565b6000819050919050565b600061234682612368565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61237e816121dc565b811461238957600080fd5b50565b612395816121ee565b81146123a057600080fd5b50565b6123ac81612204565b81146123b757600080fd5b50565b6123c381612216565b81146123ce57600080fd5b50565b6123da81612248565b81146123e557600080fd5b5056fea164736f6c634300060c000a" + }, + "GatewayRecipient": { + "abi": [ + { + "inputs": [], + "name": "gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "addresses": { + "1": null, + "3": null, + "4": null, + "5": null, + "10": null, + "42": null, + "56": null, + "69": null, + "77": null, + "97": null, + "100": null, + "122": null, + "123": null, + "137": null, + "250": null, + "1284": null, + "1287": null, + "3333": null, + "4002": null, + "4386": null, + "6666": null, + "42161": null, + "42170": null, + "42220": null, + "43113": null, + "43114": null, + "44787": null, + "80001": null, + "421611": null, + "421613": null, + "1313161554": null, + "1313161555": null + }, + "byteCode": "0x" + }, + "GatewayV2": { + "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[]" }, { - "indexed": false, "internalType": "bytes", - "name": "batch", + "name": "senderSignature", "type": "bytes" - }, - { - "indexed": false, - "internalType": "bool", - "name": "succeeded", - "type": "bool" } ], - "name": "BatchDelegated", - "type": "event" + "name": "delegateBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "initializer", + "name": "account", "type": "address" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "inputs": [], - "name": "chainId", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "nonce", "type": "uint256" + }, + { + "internalType": "address[]", + "name": "to", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "senderSignature", + "type": "bytes" } ], - "stateMutability": "view", + "name": "delegateBatchGuarded", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -5557,7 +6109,7 @@ module.exports = { "type": "bytes" } ], - "name": "delegateBatch", + "name": "delegateBatchWithGasPrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -5590,7 +6142,7 @@ module.exports = { "type": "bytes" } ], - "name": "delegateBatchWithGasPrice", + "name": "delegateBatchWithGasPriceGuarded", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -5613,6 +6165,24 @@ module.exports = { "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", @@ -5670,7 +6240,7 @@ module.exports = { "type": "bytes[]" } ], - "internalType": "struct Gateway.DelegatedBatch", + "internalType": "struct GatewayV2.DelegatedBatch", "name": "delegatedBatch", "type": "tuple" } @@ -5716,7 +6286,7 @@ module.exports = { "type": "uint256" } ], - "internalType": "struct Gateway.DelegatedBatchWithGasPrice", + "internalType": "struct GatewayV2.DelegatedBatchWithGasPrice", "name": "delegatedBatch", "type": "tuple" } @@ -5750,6 +6320,25 @@ module.exports = { "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", @@ -5776,6 +6365,19 @@ module.exports = { "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "removeGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -5816,54 +6418,67 @@ module.exports = { "outputs": [], "stateMutability": "nonpayable", "type": "function" - } - ], - "addresses": { - "1": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "3": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "4": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "5": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "10": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "42": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "56": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "69": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "77": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "97": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "100": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "122": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "123": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "137": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "250": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "1284": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "1287": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "3333": null, - "4002": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "4386": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "6666": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "42161": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "42170": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "42220": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "43113": "0xf96E0A8e408604F2c45e13c89bB395815BD5Efc6", - "43114": "0xf96E0A8e408604F2c45e13c89bB395815BD5Efc6", - "44787": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "80001": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "421611": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "421613": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "1313161554": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163", - "1313161555": "0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163" - }, - "byteCode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600046905080600181905550506123f58061006d6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063867519c61161008c5780639f255626116100665780639f255626146101fe578063b5021b161461021a578063d2c83b9a14610236578063f92c5f7c14610254576100cf565b8063867519c6146101a657806387d31313146101c25780639a8a0592146101e0576100cf565b8063231badaf146100d4578063392e53cd146100f0578063485cc9551461010e5780635afaa7bb1461012a57806373e5a13f1461014657806376db2b4c14610176575b600080fd5b6100ee60048036038101906100e99190611438565b610284565b005b6100f861037f565b6040516101059190611e71565b60405180910390f35b610128600480360381019061012391906115e0565b6103d5565b005b610144600480360381019061013f9190611563565b610561565b005b610160600480360381019061015b919061165d565b610739565b60405161016d9190611e8c565b60405180910390f35b610190600480360381019061018b919061161c565b61075e565b60405161019d9190611e8c565b60405180910390f35b6101c060048036038101906101bb91906113b9565b610788565b005b6101ca610799565b6040516101d79190611f07565b60405180910390f35b6101e86107bf565b6040516101f591906120a2565b60405180910390f35b610218600480360381019061021391906114f7565b6107c5565b005b610234600480360381019061022f9190611438565b6107d5565b005b61023e6108d1565b60405161024b9190611eec565b60405180910390f35b61026e60048036038101906102699190611390565b6108f7565b60405161027b91906120a2565b60405180910390f35b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fc90611f82565b60405180910390fd5b60006103258261031788888888610953565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061037786828686610a71565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045a90611f42565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516105559190611def565b60405180910390a15050565b60008251116105a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059c90611fc2565b60405180910390fd5b600080600090505b83518110156106f35760003073ffffffffffffffffffffffffffffffffffffffff168583815181106105db57fe5b60200260200101516040516105f09190611d0b565b6000604051808303816000865af19150503d806000811461062d576040519150601f19603f3d011682016040523d82523d6000602084013e610632565b606091505b505090508315610681578061067c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067390611f62565b60405180910390fd5b610697565b80801561068c575082155b1561069657600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106106c557fe5b6020026020010151836040516106dd93929190611e0a565b60405180910390a15080806001019150506105ad565b5080610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072b90612082565b60405180910390fd5b505050565b60006107578260000151836020015184604001518560600151610953565b9050919050565b600061078182600001518360200151846040015185606001518660800151610edc565b9050919050565b61079483338484610a71565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b6107d133338484610a71565b5050565b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084d90611f82565b60405180910390fd5b600061087782610869888888883a610edc565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108c986828686610a71565b505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061094c6001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f4290919063ffffffff16565b9050919050565b60006109ac7f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661098587610f97565b6040516020016109989493929190611c6e565b604051602081830303815290604052610ffa565b9050949350505050565b60008060009050604183511415610a675760008060006020860151925060408601519150606086015160001a9050601b8160ff1610156109f757601b810190505b601b8160ff161480610a0c5750601c8160ff16145b15610a635760018782858560405160008152602001604052604051610a349493929190611ea7565b6020604051602081039080840390855afa158015610a56573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415610ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad890611fa2565b60405180910390fd5b6000825111610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c90612062565b60405180910390fd5b8151815114610b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6090612002565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610d3d57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610bf9929190611e48565b60206040518083038186803b158015610c1157600080fd5b505afa158015610c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4991906115b7565b80610cfd5750600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610cac929190611e48565b60206040518083038186803b158015610cc457600080fd5b505afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc91906115b7565b5b610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3390611fe2565b60405180910390fd5b5b600080600090505b8251811015610ed457600073ffffffffffffffffffffffffffffffffffffffff16848281518110610d7257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff161415610dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc890611f22565b60405180910390fd5b838181518110610ddd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16838281518110610e0757fe5b60200260200101518787604051602001610e2393929190611d22565b604051602081830303815290604052604051610e3f9190611d0b565b6000604051808303816000865af19150503d8060008114610e7c576040519150601f19603f3d011682016040523d82523d6000602084013e610e81565b606091505b50508092505081610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebe90612022565b60405180910390fd5b8080600101915050610d45565b505050505050565b6000610f377f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad878787610f0e88610f97565b87604051602001610f23959493929190611cb4565b604051602081830303815290604052610ffa565b905095945050505050565b600080828401905083811015610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490612042565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015610fef5782858281518110610fb857fe5b6020026020010151604051602001610fd1929190611d5b565b60405160208183030381529060405292508080600101915050610fa3565b508192505050919050565b60006110336001543085856040516020016110189493929190611da5565b6040516020818303038152906040528051906020012061103b565b905092915050565b60008160405160200161104e9190611d7f565b604051602081830303815290604052805190602001209050919050565b60008135905061107a81612375565b92915050565b600082601f83011261109157600080fd5b81356110a461109f826120ea565b6120bd565b915081818352602084019350602081019050838560208402820111156110c957600080fd5b60005b838110156110f957816110df888261106b565b8452602084019350602083019250506001810190506110cc565b5050505092915050565b600082601f83011261111457600080fd5b813561112761112282612112565b6120bd565b9150818183526020840193506020810190508360005b8381101561116d578135860161115388826111a1565b84526020840193506020830192505060018101905061113d565b5050505092915050565b6000813590506111868161238c565b92915050565b60008151905061119b8161238c565b92915050565b600082601f8301126111b257600080fd5b81356111c56111c08261213a565b6120bd565b915080825260208301602083018583830111156111e157600080fd5b6111ec8382846122dd565b50505092915050565b600081359050611204816123a3565b92915050565b600081359050611219816123ba565b92915050565b600060a0828403121561123157600080fd5b61123b60a06120bd565b9050600061124b8482850161106b565b600083015250602061125f8482850161137b565b602083015250604082013567ffffffffffffffff81111561127f57600080fd5b61128b84828501611080565b604083015250606082013567ffffffffffffffff8111156112ab57600080fd5b6112b784828501611103565b60608301525060806112cb8482850161137b565b60808301525092915050565b6000608082840312156112e957600080fd5b6112f360806120bd565b905060006113038482850161106b565b60008301525060206113178482850161137b565b602083015250604082013567ffffffffffffffff81111561133757600080fd5b61134384828501611080565b604083015250606082013567ffffffffffffffff81111561136357600080fd5b61136f84828501611103565b60608301525092915050565b60008135905061138a816123d1565b92915050565b6000602082840312156113a257600080fd5b60006113b08482850161106b565b91505092915050565b6000806000606084860312156113ce57600080fd5b60006113dc8682870161106b565b935050602084013567ffffffffffffffff8111156113f957600080fd5b61140586828701611080565b925050604084013567ffffffffffffffff81111561142257600080fd5b61142e86828701611103565b9150509250925092565b600080600080600060a0868803121561145057600080fd5b600061145e8882890161106b565b955050602061146f8882890161137b565b945050604086013567ffffffffffffffff81111561148c57600080fd5b61149888828901611080565b935050606086013567ffffffffffffffff8111156114b557600080fd5b6114c188828901611103565b925050608086013567ffffffffffffffff8111156114de57600080fd5b6114ea888289016111a1565b9150509295509295909350565b6000806040838503121561150a57600080fd5b600083013567ffffffffffffffff81111561152457600080fd5b61153085828601611080565b925050602083013567ffffffffffffffff81111561154d57600080fd5b61155985828601611103565b9150509250929050565b6000806040838503121561157657600080fd5b600083013567ffffffffffffffff81111561159057600080fd5b61159c85828601611103565b92505060206115ad85828601611177565b9150509250929050565b6000602082840312156115c957600080fd5b60006115d78482850161118c565b91505092915050565b600080604083850312156115f357600080fd5b6000611601858286016111f5565b92505060206116128582860161120a565b9150509250929050565b60006020828403121561162e57600080fd5b600082013567ffffffffffffffff81111561164857600080fd5b6116548482850161121f565b91505092915050565b60006020828403121561166f57600080fd5b600082013567ffffffffffffffff81111561168957600080fd5b611695848285016112d7565b91505092915050565b60006116aa83836116d4565b60208301905092915050565b6116bf8161225f565b82525050565b6116ce816121dc565b82525050565b6116dd816121dc565b82525050565b6116f46116ef826121dc565b61231f565b82525050565b600061170582612176565b61170f8185612199565b935061171a83612166565b8060005b8381101561174b578151611732888261169e565b975061173d8361218c565b92505060018101905061171e565b5085935050505092915050565b611761816121ee565b82525050565b611770816121fa565b82525050565b611787611782826121fa565b612331565b82525050565b600061179882612181565b6117a281856121a4565b93506117b28185602086016122ec565b6117bb81612357565b840191505092915050565b60006117d182612181565b6117db81856121b5565b93506117eb8185602086016122ec565b80840191505092915050565b61180081612271565b82525050565b61180f81612295565b82525050565b6000611822601b836121c0565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000611862601c836121d1565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006118a2602f836121c0565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006119086017836121c0565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006119486032836121c0565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b60006119ae6025836121c0565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a146026836121c0565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a7a6028836121c0565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ae06016836121c0565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000611b206023836121c0565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611b86601e836121c0565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000611bc66020836121c0565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b6000611c06601d836121c0565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b611c4281612248565b82525050565b611c59611c5482612248565b61234d565b82525050565b611c6881612252565b82525050565b6000611c7a82876116e3565b601482019150611c8a8286611c48565b602082019150611c9a82856116fa565b9150611ca682846117c6565b915081905095945050505050565b6000611cc082886116e3565b601482019150611cd08287611c48565b602082019150611ce082866116fa565b9150611cec82856117c6565b9150611cf88284611c48565b6020820191508190509695505050505050565b6000611d1782846117c6565b915081905092915050565b6000611d2e82866117c6565b9150611d3a82856116e3565b601482019150611d4a82846116e3565b601482019150819050949350505050565b6000611d6782856117c6565b9150611d7382846117c6565b91508190509392505050565b6000611d8a82611855565b9150611d968284611776565b60208201915081905092915050565b6000611db18287611c48565b602082019150611dc182866116e3565b601482019150611dd18285611776565b602082019150611de182846117c6565b915081905095945050505050565b6000602082019050611e0460008301846116b6565b92915050565b6000606082019050611e1f60008301866116b6565b8181036020830152611e31818561178d565b9050611e406040830184611758565b949350505050565b6000604082019050611e5d60008301856116c5565b611e6a60208301846116c5565b9392505050565b6000602082019050611e866000830184611758565b92915050565b6000602082019050611ea16000830184611767565b92915050565b6000608082019050611ebc6000830187611767565b611ec96020830186611c5f565b611ed66040830185611767565b611ee36060830184611767565b95945050505050565b6000602082019050611f0160008301846117f7565b92915050565b6000602082019050611f1c6000830184611806565b92915050565b60006020820190508181036000830152611f3b81611815565b9050919050565b60006020820190508181036000830152611f5b81611895565b9050919050565b60006020820190508181036000830152611f7b816118fb565b9050919050565b60006020820190508181036000830152611f9b8161193b565b9050919050565b60006020820190508181036000830152611fbb816119a1565b9050919050565b60006020820190508181036000830152611fdb81611a07565b9050919050565b60006020820190508181036000830152611ffb81611a6d565b9050919050565b6000602082019050818103600083015261201b81611ad3565b9050919050565b6000602082019050818103600083015261203b81611b13565b9050919050565b6000602082019050818103600083015261205b81611b79565b9050919050565b6000602082019050818103600083015261207b81611bb9565b9050919050565b6000602082019050818103600083015261209b81611bf9565b9050919050565b60006020820190506120b76000830184611c39565b92915050565b6000604051905081810181811067ffffffffffffffff821117156120e057600080fd5b8060405250919050565b600067ffffffffffffffff82111561210157600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561212957600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561215157600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006121e782612228565b9050919050565b60008115159050919050565b6000819050919050565b600061220f826121dc565b9050919050565b6000612221826121dc565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061226a826122b9565b9050919050565b600061227c82612283565b9050919050565b600061228e82612228565b9050919050565b60006122a0826122a7565b9050919050565b60006122b282612228565b9050919050565b60006122c4826122cb565b9050919050565b60006122d682612228565b9050919050565b82818337600083830152505050565b60005b8381101561230a5780820151818401526020810190506122ef565b83811115612319576000848401525b50505050565b600061232a8261233b565b9050919050565b6000819050919050565b600061234682612368565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61237e816121dc565b811461238957600080fd5b50565b612395816121ee565b81146123a057600080fd5b50565b6123ac81612204565b81146123b757600080fd5b50565b6123c381612216565b81146123ce57600080fd5b50565b6123da81612248565b81146123e557600080fd5b5056fea164736f6c634300060c000a" - }, - "GatewayRecipient": { - "abi": [ + }, { - "inputs": [], - "name": "gateway", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "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", @@ -5874,13 +6489,13 @@ module.exports = { "1": null, "3": null, "4": null, - "5": null, + "5": "0xBEd52610518788B931f7825301909e7616273d47", "10": null, "42": null, "56": null, "69": null, - "77": null, - "97": null, + "77": "0xBEd52610518788B931f7825301909e7616273d47", + "97": "0xBEd52610518788B931f7825301909e7616273d47", "100": null, "122": null, "123": null, @@ -5889,22 +6504,22 @@ module.exports = { "1284": null, "1287": null, "3333": null, - "4002": null, + "4002": "0xBEd52610518788B931f7825301909e7616273d47", "4386": null, "6666": null, "42161": null, "42170": null, "42220": null, - "43113": null, + "43113": "0x9FC4DdE698E5cf1Ee8d6e2D25c835836d9af1C8F", "43114": null, "44787": null, - "80001": null, - "421611": null, + "80001": "0xBEd52610518788B931f7825301909e7616273d47", + "421611": "0xBEd52610518788B931f7825301909e7616273d47", "421613": null, "1313161554": null, "1313161555": null }, - "byteCode": "0x" + "byteCode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a" }, "Guarded": { "abi": [ @@ -22427,5 +23042,43 @@ module.exports = { "1313161555": null }, "byteCode": "0x608060405234801561001057600080fd5b5061002d61002261003260201b60201c565b61003a60201b60201c565b6100fe565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612020806200010e6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638f5d90e01161008c578063b9cff16211610066578063b9cff16214610237578063e0e7a91314610267578063f2fde38b14610283578063f31faefb1461029f576100ea565b80638f5d90e0146101e1578063916c3470146101fd5780639fa92f9d14610219576100ea565b80636ef0f37f116100c85780636ef0f37f1461017f578063715018a61461019b5780638d3638f4146101a55780638da5cb5b146101c3576100ea565b8063427ebef5146100ef5780635190bc531461011f5780635f8b1dba1461014f575b600080fd5b6101096004803603810190610104919061148e565b6102bb565b60405161011691906114e9565b60405180910390f35b61013960048036038101906101349190611504565b61032f565b60405161014691906114e9565b60405180910390f35b61016960048036038101906101649190611504565b610391565b6040516101769190611540565b60405180910390f35b61019960048036038101906101949190611504565b6103b4565b005b6101a3610474565b005b6101ad6104fc565b6040516101ba9190611540565b60405180910390f35b6101cb610594565b6040516101d8919061156a565b60405180910390f35b6101fb60048036038101906101f69190611504565b6105bd565b005b610217600480360381019061021291906115b1565b610645565b005b61022161077a565b60405161022e9190611663565b60405180910390f35b610251600480360381019061024c919061167e565b6107a0565b60405161025e919061156a565b60405180910390f35b610281600480360381019061027c9190611827565b6107d3565b005b61029d60048036038101906102989190611504565b610a3b565b005b6102b960048036038101906102b4919061148e565b610b32565b005b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008363ffffffff1663ffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600080600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900463ffffffff1663ffffffff1614159050919050565b60026020528060005260406000206000915054906101000a900463ffffffff1681565b6103bc610cb5565b73ffffffffffffffffffffffffffffffffffffffff166103da610594565b73ffffffffffffffffffffffffffffffffffffffff1614610430576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610427906118f3565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61047c610cb5565b73ffffffffffffffffffffffffffffffffffffffff1661049a610594565b73ffffffffffffffffffffffffffffffffffffffff16146104f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e7906118f3565b60405180910390fd5b6104fa6000610cbd565b565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638d3638f46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561056b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058f9190611928565b905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6105c5610cb5565b73ffffffffffffffffffffffffffffffffffffffff166105e3610594565b73ffffffffffffffffffffffffffffffffffffffff1614610639576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610630906118f3565b60405180910390fd5b61064281610d81565b50565b61064d610cb5565b73ffffffffffffffffffffffffffffffffffffffff1661066b610594565b73ffffffffffffffffffffffffffffffffffffffff16146106c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b8906118f3565b60405180910390fd5b80600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008463ffffffff1663ffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508163ffffffff167f517de16b526853f481451c5151e87484e1b251ec7d0302efa1019c2ece179c2c848360405161076d929190611955565b60405180910390a2505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600360008563ffffffff1663ffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d906119ca565b60405180910390fd5b61088f83610ed5565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663df034cd06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091491906119ff565b73ffffffffffffffffffffffffffffffffffffffff161461096a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161096190611a78565b60405180910390fd5b60006109808561097984610ee2565b8686610f05565b9050600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008663ffffffff1663ffffffff16815260200190815260200160002060009054906101000a900460ff16610a2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2290611ae4565b60405180910390fd5b610a3482610d81565b5050505050565b610a43610cb5565b73ffffffffffffffffffffffffffffffffffffffff16610a61610594565b73ffffffffffffffffffffffffffffffffffffffff1614610ab7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aae906118f3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1d90611b76565b60405180910390fd5b610b2f81610cbd565b50565b610b3a610cb5565b73ffffffffffffffffffffffffffffffffffffffff16610b58610594565b73ffffffffffffffffffffffffffffffffffffffff1614610bae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba5906118f3565b60405180910390fd5b610bb782610d81565b80600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548163ffffffff021916908363ffffffff16021790555081600360008363ffffffff1663ffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508063ffffffff167f8440df9bf8a8542634a9eb196da1735b786ed9aa2fc12b080ac34c5fa81a923483604051610ca9919061156a565b60405180910390a25050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900463ffffffff1690506000600360008363ffffffff1663ffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548163ffffffff021916908363ffffffff1602179055508063ffffffff167fce1533133fb359ace801d3176bbad25ace030d714aed35e38a6293c8a60b115b83604051610ec9919061156a565b60405180910390a25050565b60008160001c9050919050565b60008173ffffffffffffffffffffffffffffffffffffffff1660001b9050919050565b600080610f1185610ed5565b73ffffffffffffffffffffffffffffffffffffffff166345630b1a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7f9190611bab565b90506000818786604051602001610f9893929190611c2f565b604051602081830303815290604052805190602001209050610fb981610fd1565b9050610fc58185611001565b92505050949350505050565b600081604051602001610fe49190611cc3565b604051602081830303815290604052805190602001209050919050565b60008060006110108585611028565b9150915061101d816110a9565b819250505092915050565b60008060418351036110695760008060006020860151925060408601519150606086015160001a905061105d87828585611275565b945094505050506110a2565b604083510361109957600080602085015191506040850151905061108e868383611381565b9350935050506110a2565b60006002915091505b9250929050565b600060048111156110bd576110bc611ce9565b5b8160048111156110d0576110cf611ce9565b5b031561127257600160048111156110ea576110e9611ce9565b5b8160048111156110fd576110fc611ce9565b5b0361113d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113490611d64565b60405180910390fd5b6002600481111561115157611150611ce9565b5b81600481111561116457611163611ce9565b5b036111a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119b90611dd0565b60405180910390fd5b600360048111156111b8576111b7611ce9565b5b8160048111156111cb576111ca611ce9565b5b0361120b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120290611e62565b60405180910390fd5b60048081111561121e5761121d611ce9565b5b81600481111561123157611230611ce9565b5b03611271576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126890611ef4565b60405180910390fd5b5b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156112b0576000600391509150611378565b601b8560ff16141580156112c85750601c8560ff1614155b156112da576000600491509150611378565b6000600187878787604051600081526020016040526040516112ff9493929190611f3f565b6020604051602081039080840390855afa158015611321573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361136f57600060019250925050611378565b80600092509250505b94509492505050565b60008060007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60001b841690506000601b60ff8660001c901c6113c49190611fbd565b90506113d287828885611275565b935093505050935093915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061141f826113f4565b9050919050565b61142f81611414565b811461143a57600080fd5b50565b60008135905061144c81611426565b92915050565b600063ffffffff82169050919050565b61146b81611452565b811461147657600080fd5b50565b60008135905061148881611462565b92915050565b600080604083850312156114a5576114a46113ea565b5b60006114b38582860161143d565b92505060206114c485828601611479565b9150509250929050565b60008115159050919050565b6114e3816114ce565b82525050565b60006020820190506114fe60008301846114da565b92915050565b60006020828403121561151a576115196113ea565b5b60006115288482850161143d565b91505092915050565b61153a81611452565b82525050565b60006020820190506115556000830184611531565b92915050565b61156481611414565b82525050565b600060208201905061157f600083018461155b565b92915050565b61158e816114ce565b811461159957600080fd5b50565b6000813590506115ab81611585565b92915050565b6000806000606084860312156115ca576115c96113ea565b5b60006115d88682870161143d565b93505060206115e986828701611479565b92505060406115fa8682870161159c565b9150509250925092565b6000819050919050565b600061162961162461161f846113f4565b611604565b6113f4565b9050919050565b600061163b8261160e565b9050919050565b600061164d82611630565b9050919050565b61165d81611642565b82525050565b60006020820190506116786000830184611654565b92915050565b600060208284031215611694576116936113ea565b5b60006116a284828501611479565b91505092915050565b6000819050919050565b6116be816116ab565b81146116c957600080fd5b50565b6000813590506116db816116b5565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611734826116eb565b810181811067ffffffffffffffff82111715611753576117526116fc565b5b80604052505050565b60006117666113e0565b9050611772828261172b565b919050565b600067ffffffffffffffff821115611792576117916116fc565b5b61179b826116eb565b9050602081019050919050565b82818337600083830152505050565b60006117ca6117c584611777565b61175c565b9050828152602081018484840111156117e6576117e56116e6565b5b6117f18482856117a8565b509392505050565b600082601f83011261180e5761180d6116e1565b5b813561181e8482602086016117b7565b91505092915050565b6000806000606084860312156118405761183f6113ea565b5b600061184e86828701611479565b935050602061185f868287016116cc565b925050604084013567ffffffffffffffff8111156118805761187f6113ef565b5b61188c868287016117f9565b9150509250925092565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006118dd602083611896565b91506118e8826118a7565b602082019050919050565b6000602082019050818103600083015261190c816118d0565b9050919050565b60008151905061192281611462565b92915050565b60006020828403121561193e5761193d6113ea565b5b600061194c84828501611913565b91505092915050565b600060408201905061196a600083018561155b565b61197760208301846114da565b9392505050565b7f217265706c696361206578697374730000000000000000000000000000000000600082015250565b60006119b4600f83611896565b91506119bf8261197e565b602082019050919050565b600060208201905081810360008301526119e3816119a7565b9050919050565b6000815190506119f981611426565b92915050565b600060208284031215611a1557611a146113ea565b5b6000611a23848285016119ea565b91505092915050565b7f2163757272656e74207570646174657200000000000000000000000000000000600082015250565b6000611a62601083611896565b9150611a6d82611a2c565b602082019050919050565b60006020820190508181036000830152611a9181611a55565b9050919050565b7f2176616c69642077617463686572000000000000000000000000000000000000600082015250565b6000611ace600e83611896565b9150611ad982611a98565b602082019050919050565b60006020820190508181036000830152611afd81611ac1565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000611b60602683611896565b9150611b6b82611b04565b604082019050919050565b60006020820190508181036000830152611b8f81611b53565b9050919050565b600081519050611ba5816116b5565b92915050565b600060208284031215611bc157611bc06113ea565b5b6000611bcf84828501611b96565b91505092915050565b6000819050919050565b611bf3611bee826116ab565b611bd8565b82525050565b60008160e01b9050919050565b6000611c1182611bf9565b9050919050565b611c29611c2482611452565b611c06565b82525050565b6000611c3b8286611be2565b602082019150611c4b8285611c18565b600482019150611c5b8284611be2565b602082019150819050949350505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000611cad601c83611c6c565b9150611cb882611c77565b601c82019050919050565b6000611cce82611ca0565b9150611cda8284611be2565b60208201915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000611d4e601883611896565b9150611d5982611d18565b602082019050919050565b60006020820190508181036000830152611d7d81611d41565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000611dba601f83611896565b9150611dc582611d84565b602082019050919050565b60006020820190508181036000830152611de981611dad565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000611e4c602283611896565b9150611e5782611df0565b604082019050919050565b60006020820190508181036000830152611e7b81611e3f565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000611ede602283611896565b9150611ee982611e82565b604082019050919050565b60006020820190508181036000830152611f0d81611ed1565b9050919050565b611f1d816116ab565b82525050565b600060ff82169050919050565b611f3981611f23565b82525050565b6000608082019050611f546000830187611f14565b611f616020830186611f30565b611f6e6040830185611f14565b611f7b6060830184611f14565b95945050505050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611fc882611f84565b9150611fd383611f84565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561200857612007611f8e565b5b82820190509291505056fea164736f6c634300080f000a" + }, + "console": { + "abi": [], + "addresses": { + "1": null, + "3": null, + "4": null, + "5": null, + "10": null, + "42": null, + "56": null, + "69": null, + "77": null, + "97": null, + "100": null, + "122": null, + "123": null, + "137": null, + "250": null, + "1284": null, + "1287": null, + "3333": null, + "4002": null, + "4386": null, + "6666": null, + "42161": null, + "42170": null, + "42220": null, + "43113": null, + "43114": null, + "44787": null, + "80001": null, + "421611": null, + "421613": null, + "1313161554": null, + "1313161555": null + }, + "byteCode": "0x602d6050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a" } }; diff --git a/dist/deploy/008_create-gateway-v2.d.ts b/dist/deploy/008_create-gateway-v2.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/deploy/008_create-gateway-v2.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/deploy/008_create-gateway-v2.js b/dist/deploy/008_create-gateway-v2.js new file mode 100644 index 00000000..a85e300f --- /dev/null +++ b/dist/deploy/008_create-gateway-v2.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async (hre) => { + const { deployments: { deploy }, getNamedAccounts, } = hre; + const { from } = await getNamedAccounts(); + await deploy('GatewayV2', { + from, + log: true, + }); +}; +func.tags = ['create', 'gateway-v2']; +module.exports = func; diff --git a/dist/deploy/108_setup-gateway-v2.d.ts b/dist/deploy/108_setup-gateway-v2.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/dist/deploy/108_setup-gateway-v2.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/deploy/108_setup-gateway-v2.js b/dist/deploy/108_setup-gateway-v2.js new file mode 100644 index 00000000..0ad01e90 --- /dev/null +++ b/dist/deploy/108_setup-gateway-v2.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const func = async (hre) => { + const { deployments: { get, log, execute, read }, getNamedAccounts, } = hre; + const { from } = await getNamedAccounts(); + if (await read('GatewayV2', 'isInitialized')) { + log('GatewayV2 already initialized'); + } + else { + const externalAccountRegistry = await get('ExternalAccountRegistry'); + const personalAccountRegistry = await get('PersonalAccountRegistry'); + await execute('GatewayV2', { + from, + log: true, + }, 'initialize', externalAccountRegistry.address, personalAccountRegistry.address); + } +}; +func.tags = ['setup', 'gateway-v2']; +module.exports = func; diff --git a/dist/extensions/constants.js b/dist/extensions/constants.js index 0106cbc8..3715e68c 100644 --- a/dist/extensions/constants.js +++ b/dist/extensions/constants.js @@ -112,7 +112,7 @@ exports.NETWORK_CONFIGS = { }, [NetworkNames.Mumbai]: { chainId: 80001, - defaultProviderUrl: "https://rpc-mumbai.maticvigil.com", + defaultProviderUrl: "https://matic-mumbai.chainstacklabs.com", defaultGasPrice: 5, explorer: "https://mumbai.polygonscan.com", }, diff --git a/dist/typings/GatewayV2.d.ts b/dist/typings/GatewayV2.d.ts new file mode 100644 index 00000000..ca286554 --- /dev/null +++ b/dist/typings/GatewayV2.d.ts @@ -0,0 +1,398 @@ +import { BaseContract, BigNumber, BigNumberish, BytesLike, CallOverrides, ContractTransaction, Overrides, PopulatedTransaction, Signer, utils } from "ethers"; +import { FunctionFragment, Result, EventFragment } from "@ethersproject/abi"; +import { Listener, Provider } from "@ethersproject/providers"; +import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; +export declare type DelegatedBatchStruct = { + account: string; + nonce: BigNumberish; + to: string[]; + data: BytesLike[]; +}; +export declare type DelegatedBatchStructOutput = [ + string, + BigNumber, + string[], + string[] +] & { + account: string; + nonce: BigNumber; + to: string[]; + data: string[]; +}; +export declare type DelegatedBatchWithGasPriceStruct = { + account: string; + nonce: BigNumberish; + to: string[]; + data: BytesLike[]; + gasPrice: BigNumberish; +}; +export declare type DelegatedBatchWithGasPriceStructOutput = [ + string, + BigNumber, + string[], + string[], + BigNumber +] & { + account: string; + nonce: BigNumber; + to: string[]; + data: string[]; + gasPrice: BigNumber; +}; +export interface GatewayV2Interface extends utils.Interface { + functions: { + "addGuardian(address)": FunctionFragment; + "chainId()": FunctionFragment; + "delegateBatch(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatchGuarded(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatchWithGasPriceGuarded(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatches(bytes[],bool)": FunctionFragment; + "delegateBatchesGuarded(bytes[],bool)": FunctionFragment; + "externalAccountRegistry()": FunctionFragment; + "getAccountNextNonce(address)": FunctionFragment; + "hashDelegatedBatch((address,uint256,address[],bytes[]))": FunctionFragment; + "hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))": FunctionFragment; + "initialize(address,address)": FunctionFragment; + "isGuardian(address)": FunctionFragment; + "isInitialized()": FunctionFragment; + "personalAccountRegistry()": FunctionFragment; + "removeGuardian(address)": FunctionFragment; + "sendBatch(address[],bytes[])": FunctionFragment; + "sendBatchFromAccount(address,address[],bytes[])": FunctionFragment; + "sendBatchFromAccountGuarded(address,address[],bytes[])": FunctionFragment; + "sendBatchGuarded(address[],bytes[])": FunctionFragment; + "verifyGuardianSignature(bytes32,bytes)": FunctionFragment; + }; + encodeFunctionData(functionFragment: "addGuardian", values: [string]): string; + encodeFunctionData(functionFragment: "chainId", values?: undefined): string; + encodeFunctionData(functionFragment: "delegateBatch", values: [string, BigNumberish, string[], BytesLike[], BytesLike]): string; + encodeFunctionData(functionFragment: "delegateBatchGuarded", values: [string, BigNumberish, string[], BytesLike[], BytesLike]): string; + encodeFunctionData(functionFragment: "delegateBatchWithGasPrice", values: [string, BigNumberish, string[], BytesLike[], BytesLike]): string; + encodeFunctionData(functionFragment: "delegateBatchWithGasPriceGuarded", values: [string, BigNumberish, string[], BytesLike[], BytesLike]): string; + encodeFunctionData(functionFragment: "delegateBatches", values: [BytesLike[], boolean]): string; + encodeFunctionData(functionFragment: "delegateBatchesGuarded", values: [BytesLike[], boolean]): string; + encodeFunctionData(functionFragment: "externalAccountRegistry", values?: undefined): string; + encodeFunctionData(functionFragment: "getAccountNextNonce", values: [string]): string; + encodeFunctionData(functionFragment: "hashDelegatedBatch", values: [DelegatedBatchStruct]): string; + encodeFunctionData(functionFragment: "hashDelegatedBatchWithGasPrice", values: [DelegatedBatchWithGasPriceStruct]): string; + encodeFunctionData(functionFragment: "initialize", values: [string, string]): string; + encodeFunctionData(functionFragment: "isGuardian", values: [string]): string; + encodeFunctionData(functionFragment: "isInitialized", values?: undefined): string; + encodeFunctionData(functionFragment: "personalAccountRegistry", values?: undefined): string; + encodeFunctionData(functionFragment: "removeGuardian", values: [string]): string; + encodeFunctionData(functionFragment: "sendBatch", values: [string[], BytesLike[]]): string; + encodeFunctionData(functionFragment: "sendBatchFromAccount", values: [string, string[], BytesLike[]]): string; + encodeFunctionData(functionFragment: "sendBatchFromAccountGuarded", values: [string, string[], BytesLike[]]): string; + encodeFunctionData(functionFragment: "sendBatchGuarded", values: [string[], BytesLike[]]): string; + encodeFunctionData(functionFragment: "verifyGuardianSignature", values: [BytesLike, BytesLike]): string; + decodeFunctionResult(functionFragment: "addGuardian", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "chainId", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "delegateBatch", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "delegateBatchGuarded", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "delegateBatchWithGasPrice", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "delegateBatchWithGasPriceGuarded", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "delegateBatches", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "delegateBatchesGuarded", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "externalAccountRegistry", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "getAccountNextNonce", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "hashDelegatedBatch", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "hashDelegatedBatchWithGasPrice", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "initialize", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "isGuardian", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "isInitialized", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "personalAccountRegistry", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "removeGuardian", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "sendBatch", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "sendBatchFromAccount", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "sendBatchFromAccountGuarded", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "sendBatchGuarded", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "verifyGuardianSignature", data: BytesLike): Result; + events: { + "BatchDelegated(address,bytes,bool)": EventFragment; + "GuardianAdded(address,address)": EventFragment; + "GuardianRemoved(address,address)": EventFragment; + "Initialized(address)": EventFragment; + }; + getEvent(nameOrSignatureOrTopic: "BatchDelegated"): EventFragment; + getEvent(nameOrSignatureOrTopic: "GuardianAdded"): EventFragment; + getEvent(nameOrSignatureOrTopic: "GuardianRemoved"): EventFragment; + getEvent(nameOrSignatureOrTopic: "Initialized"): EventFragment; +} +export declare type BatchDelegatedEvent = TypedEvent<[ + string, + string, + boolean +], { + sender: string; + batch: string; + succeeded: boolean; +}>; +export declare type BatchDelegatedEventFilter = TypedEventFilter; +export declare type GuardianAddedEvent = TypedEvent<[ + string, + string +], { + sender: string; + guardian: string; +}>; +export declare type GuardianAddedEventFilter = TypedEventFilter; +export declare type GuardianRemovedEvent = TypedEvent<[ + string, + string +], { + sender: string; + guardian: string; +}>; +export declare type GuardianRemovedEventFilter = TypedEventFilter; +export declare type InitializedEvent = TypedEvent<[string], { + initializer: string; +}>; +export declare type InitializedEventFilter = TypedEventFilter; +export interface GatewayV2 extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + interface: GatewayV2Interface; + queryFilter(event: TypedEventFilter, fromBlockOrBlockhash?: string | number | undefined, toBlock?: string | number | undefined): Promise>; + listeners(eventFilter?: TypedEventFilter): Array>; + listeners(eventName?: string): Array; + removeAllListeners(eventFilter: TypedEventFilter): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + functions: { + addGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + chainId(overrides?: CallOverrides): Promise<[BigNumber]>; + delegateBatch(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPrice(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPriceGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatches(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchesGuarded(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + externalAccountRegistry(overrides?: CallOverrides): Promise<[string]>; + getAccountNextNonce(account: string, overrides?: CallOverrides): Promise<[BigNumber]>; + hashDelegatedBatch(delegatedBatch: DelegatedBatchStruct, overrides?: CallOverrides): Promise<[string]>; + hashDelegatedBatchWithGasPrice(delegatedBatch: DelegatedBatchWithGasPriceStruct, overrides?: CallOverrides): Promise<[string]>; + initialize(externalAccountRegistry_: string, personalAccountRegistry_: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + isGuardian(guardian: string, overrides?: CallOverrides): Promise<[boolean]>; + isInitialized(overrides?: CallOverrides): Promise<[boolean]>; + personalAccountRegistry(overrides?: CallOverrides): Promise<[string]>; + removeGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatch(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccount(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccountGuarded(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchGuarded(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + verifyGuardianSignature(messageHash: BytesLike, signature: BytesLike, overrides?: CallOverrides): Promise<[boolean]>; + }; + addGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + chainId(overrides?: CallOverrides): Promise; + delegateBatch(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPrice(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPriceGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatches(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchesGuarded(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + externalAccountRegistry(overrides?: CallOverrides): Promise; + getAccountNextNonce(account: string, overrides?: CallOverrides): Promise; + hashDelegatedBatch(delegatedBatch: DelegatedBatchStruct, overrides?: CallOverrides): Promise; + hashDelegatedBatchWithGasPrice(delegatedBatch: DelegatedBatchWithGasPriceStruct, overrides?: CallOverrides): Promise; + initialize(externalAccountRegistry_: string, personalAccountRegistry_: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + isGuardian(guardian: string, overrides?: CallOverrides): Promise; + isInitialized(overrides?: CallOverrides): Promise; + personalAccountRegistry(overrides?: CallOverrides): Promise; + removeGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatch(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccount(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccountGuarded(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchGuarded(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + verifyGuardianSignature(messageHash: BytesLike, signature: BytesLike, overrides?: CallOverrides): Promise; + callStatic: { + addGuardian(guardian: string, overrides?: CallOverrides): Promise; + chainId(overrides?: CallOverrides): Promise; + delegateBatch(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: CallOverrides): Promise; + delegateBatchGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: CallOverrides): Promise; + delegateBatchWithGasPrice(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: CallOverrides): Promise; + delegateBatchWithGasPriceGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: CallOverrides): Promise; + delegateBatches(batches: BytesLike[], revertOnFailure: boolean, overrides?: CallOverrides): Promise; + delegateBatchesGuarded(batches: BytesLike[], revertOnFailure: boolean, overrides?: CallOverrides): Promise; + externalAccountRegistry(overrides?: CallOverrides): Promise; + getAccountNextNonce(account: string, overrides?: CallOverrides): Promise; + hashDelegatedBatch(delegatedBatch: DelegatedBatchStruct, overrides?: CallOverrides): Promise; + hashDelegatedBatchWithGasPrice(delegatedBatch: DelegatedBatchWithGasPriceStruct, overrides?: CallOverrides): Promise; + initialize(externalAccountRegistry_: string, personalAccountRegistry_: string, overrides?: CallOverrides): Promise; + isGuardian(guardian: string, overrides?: CallOverrides): Promise; + isInitialized(overrides?: CallOverrides): Promise; + personalAccountRegistry(overrides?: CallOverrides): Promise; + removeGuardian(guardian: string, overrides?: CallOverrides): Promise; + sendBatch(to: string[], data: BytesLike[], overrides?: CallOverrides): Promise; + sendBatchFromAccount(account: string, to: string[], data: BytesLike[], overrides?: CallOverrides): Promise; + sendBatchFromAccountGuarded(account: string, to: string[], data: BytesLike[], overrides?: CallOverrides): Promise; + sendBatchGuarded(to: string[], data: BytesLike[], overrides?: CallOverrides): Promise; + verifyGuardianSignature(messageHash: BytesLike, signature: BytesLike, overrides?: CallOverrides): Promise; + }; + filters: { + "BatchDelegated(address,bytes,bool)"(sender?: null, batch?: null, succeeded?: null): BatchDelegatedEventFilter; + BatchDelegated(sender?: null, batch?: null, succeeded?: null): BatchDelegatedEventFilter; + "GuardianAdded(address,address)"(sender?: null, guardian?: null): GuardianAddedEventFilter; + GuardianAdded(sender?: null, guardian?: null): GuardianAddedEventFilter; + "GuardianRemoved(address,address)"(sender?: null, guardian?: null): GuardianRemovedEventFilter; + GuardianRemoved(sender?: null, guardian?: null): GuardianRemovedEventFilter; + "Initialized(address)"(initializer?: null): InitializedEventFilter; + Initialized(initializer?: null): InitializedEventFilter; + }; + estimateGas: { + addGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + chainId(overrides?: CallOverrides): Promise; + delegateBatch(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPrice(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPriceGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatches(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchesGuarded(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + externalAccountRegistry(overrides?: CallOverrides): Promise; + getAccountNextNonce(account: string, overrides?: CallOverrides): Promise; + hashDelegatedBatch(delegatedBatch: DelegatedBatchStruct, overrides?: CallOverrides): Promise; + hashDelegatedBatchWithGasPrice(delegatedBatch: DelegatedBatchWithGasPriceStruct, overrides?: CallOverrides): Promise; + initialize(externalAccountRegistry_: string, personalAccountRegistry_: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + isGuardian(guardian: string, overrides?: CallOverrides): Promise; + isInitialized(overrides?: CallOverrides): Promise; + personalAccountRegistry(overrides?: CallOverrides): Promise; + removeGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatch(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccount(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccountGuarded(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchGuarded(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + verifyGuardianSignature(messageHash: BytesLike, signature: BytesLike, overrides?: CallOverrides): Promise; + }; + populateTransaction: { + addGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + chainId(overrides?: CallOverrides): Promise; + delegateBatch(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPrice(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchWithGasPriceGuarded(account: string, nonce: BigNumberish, to: string[], data: BytesLike[], senderSignature: BytesLike, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatches(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + delegateBatchesGuarded(batches: BytesLike[], revertOnFailure: boolean, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + externalAccountRegistry(overrides?: CallOverrides): Promise; + getAccountNextNonce(account: string, overrides?: CallOverrides): Promise; + hashDelegatedBatch(delegatedBatch: DelegatedBatchStruct, overrides?: CallOverrides): Promise; + hashDelegatedBatchWithGasPrice(delegatedBatch: DelegatedBatchWithGasPriceStruct, overrides?: CallOverrides): Promise; + initialize(externalAccountRegistry_: string, personalAccountRegistry_: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + isGuardian(guardian: string, overrides?: CallOverrides): Promise; + isInitialized(overrides?: CallOverrides): Promise; + personalAccountRegistry(overrides?: CallOverrides): Promise; + removeGuardian(guardian: string, overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatch(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccount(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchFromAccountGuarded(account: string, to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + sendBatchGuarded(to: string[], data: BytesLike[], overrides?: Overrides & { + from?: string | Promise; + }): Promise; + verifyGuardianSignature(messageHash: BytesLike, signature: BytesLike, overrides?: CallOverrides): Promise; + }; +} diff --git a/dist/typings/GatewayV2.js b/dist/typings/GatewayV2.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/dist/typings/GatewayV2.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/typings/factories/GatewayV2__factory.d.ts b/dist/typings/factories/GatewayV2__factory.d.ts new file mode 100644 index 00000000..a1c7d92f --- /dev/null +++ b/dist/typings/factories/GatewayV2__factory.d.ts @@ -0,0 +1,74 @@ +import { Signer, ContractFactory, Overrides } from "ethers"; +import { Provider, TransactionRequest } from "@ethersproject/providers"; +import type { GatewayV2, GatewayV2Interface } from "../GatewayV2"; +declare type GatewayV2ConstructorParams = [signer?: Signer] | ConstructorParameters; +export declare class GatewayV2__factory extends ContractFactory { + constructor(...args: GatewayV2ConstructorParams); + deploy(overrides?: Overrides & { + from?: string | Promise; + }): Promise; + getDeployTransaction(overrides?: Overrides & { + from?: string | Promise; + }): TransactionRequest; + attach(address: string): GatewayV2; + connect(signer: Signer): GatewayV2__factory; + static readonly bytecode = "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a"; + static readonly abi: ({ + inputs: any[]; + stateMutability: string; + type: string; + anonymous?: undefined; + name?: undefined; + outputs?: undefined; + } | { + anonymous: boolean; + inputs: { + indexed: boolean; + internalType: string; + name: string; + type: string; + }[]; + name: string; + type: string; + stateMutability?: undefined; + outputs?: undefined; + } | { + inputs: { + internalType: string; + name: string; + type: string; + }[]; + name: string; + outputs: { + internalType: string; + name: string; + type: string; + }[]; + stateMutability: string; + type: string; + anonymous?: undefined; + } | { + inputs: { + components: { + internalType: string; + name: string; + type: string; + }[]; + internalType: string; + name: string; + type: string; + }[]; + name: string; + outputs: { + internalType: string; + name: string; + type: string; + }[]; + stateMutability: string; + type: string; + anonymous?: undefined; + })[]; + static createInterface(): GatewayV2Interface; + static connect(address: string, signerOrProvider: Signer | Provider): GatewayV2; +} +export {}; diff --git a/dist/typings/factories/GatewayV2__factory.js b/dist/typings/factories/GatewayV2__factory.js new file mode 100644 index 00000000..555d5aae --- /dev/null +++ b/dist/typings/factories/GatewayV2__factory.js @@ -0,0 +1,615 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GatewayV2__factory = void 0; +const ethers_1 = require("ethers"); +const _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", + }, +]; +const _bytecode = "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a"; +const isSuperArgs = (xs) => xs.length > 1; +class GatewayV2__factory extends ethers_1.ContractFactory { + constructor(...args) { + if (isSuperArgs(args)) { + super(...args); + } + else { + super(_abi, _bytecode, args[0]); + } + } + deploy(overrides) { + return super.deploy(overrides || {}); + } + getDeployTransaction(overrides) { + return super.getDeployTransaction(overrides || {}); + } + attach(address) { + return super.attach(address); + } + connect(signer) { + return super.connect(signer); + } + static createInterface() { + return new ethers_1.utils.Interface(_abi); + } + static connect(address, signerOrProvider) { + return new ethers_1.Contract(address, _abi, signerOrProvider); + } +} +exports.GatewayV2__factory = GatewayV2__factory; +GatewayV2__factory.bytecode = _bytecode; +GatewayV2__factory.abi = _abi; diff --git a/dist/typings/index.d.ts b/dist/typings/index.d.ts index d32fa017..8cb617a7 100644 --- a/dist/typings/index.d.ts +++ b/dist/typings/index.d.ts @@ -83,6 +83,7 @@ export type { ENSTextResolver } from "./ENSTextResolver"; export type { ExternalAccountRegistry } from "./ExternalAccountRegistry"; export type { Gateway } from "./Gateway"; export type { GatewayRecipient } from "./GatewayRecipient"; +export type { GatewayV2 } from "./GatewayV2"; export type { GatewayRecipientMock } from "./GatewayRecipientMock"; export type { PaymentDepositAccount } from "./PaymentDepositAccount"; export type { PaymentRegistry } from "./PaymentRegistry"; @@ -174,6 +175,7 @@ export { ENSTextResolver__factory } from "./factories/ENSTextResolver__factory"; export { ExternalAccountRegistry__factory } from "./factories/ExternalAccountRegistry__factory"; export { Gateway__factory } from "./factories/Gateway__factory"; export { GatewayRecipient__factory } from "./factories/GatewayRecipient__factory"; +export { GatewayV2__factory } from "./factories/GatewayV2__factory"; export { GatewayRecipientMock__factory } from "./factories/GatewayRecipientMock__factory"; export { PaymentDepositAccount__factory } from "./factories/PaymentDepositAccount__factory"; export { PaymentRegistry__factory } from "./factories/PaymentRegistry__factory"; diff --git a/dist/typings/index.js b/dist/typings/index.js index 23bccf2b..3617abac 100644 --- a/dist/typings/index.js +++ b/dist/typings/index.js @@ -1,7 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StargateFacet__factory = exports.OwnershipFacet__factory = exports.HopFacet__factory = exports.DiamondLoupeFacet__factory = exports.DiamondCutFacet__factory = exports.ConnextFacet__factory = exports.CBridgeFacet__factory = exports.Diamond__factory = exports.ISuperfluidToken__factory = exports.ISuperAgreement__factory = exports.IERC20__factory = exports.Ownable__factory = exports.ContextUpgradeable__factory = exports.IERC20Upgradeable__factory = exports.IERC20MetadataUpgradeable__factory = exports.ERC20BurnableUpgradeable__factory = exports.ERC20Upgradeable__factory = exports.ReentrancyGuardUpgradeable__factory = exports.Initializable__factory = exports.OwnableUpgradeable__factory = exports.TypedMemView__factory = exports.IUpdaterManager__factory = exports.IMessageRecipient__factory = exports.XAppConnectionManager__factory = exports.Version0__factory = exports.Replica__factory = exports.QueueManager__factory = exports.NomadBase__factory = exports.MerkleTreeManager__factory = exports.Home__factory = exports.XAppConnectionClient__factory = exports.Version__factory = exports.Router__factory = exports.ProposedOwnableUpgradeable__factory = exports.ProposedOwnable__factory = exports.IProposedOwnable__factory = exports.RelayerFeeRouter__factory = exports.PromiseRouter__factory = exports.ICallback__factory = exports.SwapUtils__factory = exports.AmplificationUtils__factory = exports.IWrapped__factory = exports.ITokenRegistry__factory = exports.IStableSwap__factory = exports.ISponsorVault__factory = exports.IExecutor__factory = exports.IDiamondCut__factory = exports.IConnextHandler__factory = exports.IBridgeToken__factory = exports.LPToken__factory = void 0; -exports.WrappedWeiToken__factory = exports.PersonalAccountRegistry__factory = exports.PersonalAccountImplementationV1__factory = exports.PaymentRegistry__factory = exports.PaymentDepositAccount__factory = exports.GatewayRecipientMock__factory = exports.GatewayRecipient__factory = exports.Gateway__factory = exports.ExternalAccountRegistry__factory = exports.ENSTextResolver__factory = exports.ENSPubKeyResolver__factory = exports.ENSNameResolver__factory = exports.ENSAddressResolver__factory = exports.ENSReverseRegistrar__factory = exports.ENSRegistry__factory = exports.ENSHelper__factory = exports.ENSController__factory = exports.ERC20Token__factory = exports.SignatureValidator__factory = exports.ReentrancyGuard__factory = exports.BalancesHelperV2__factory = exports.BalancesHelper__factory = exports.AccountRegistryMock__factory = exports.AccountImplementationV1Mock__factory = exports.AccountControllerMock__factory = exports.AccountRegistry__factory = exports.AccountImplementationV1__factory = exports.AccountController__factory = exports.AccountBase__factory = exports.Account__factory = exports.GuardedMock__factory = exports.Guarded__factory = exports.Controlled__factory = exports.LibDiamond__factory = exports.IStargateRouter__factory = exports.IStargateReceiver__factory = exports.IHopBridge__factory = exports.IERC173__factory = exports.IERC165__factory = exports.IDiamondLoupe__factory = exports.ICBridge__factory = void 0; +exports.WrappedWeiToken__factory = exports.PersonalAccountRegistry__factory = exports.PersonalAccountImplementationV1__factory = exports.PaymentRegistry__factory = exports.PaymentDepositAccount__factory = exports.GatewayRecipientMock__factory = exports.GatewayV2__factory = exports.GatewayRecipient__factory = exports.Gateway__factory = exports.ExternalAccountRegistry__factory = exports.ENSTextResolver__factory = exports.ENSPubKeyResolver__factory = exports.ENSNameResolver__factory = exports.ENSAddressResolver__factory = exports.ENSReverseRegistrar__factory = exports.ENSRegistry__factory = exports.ENSHelper__factory = exports.ENSController__factory = exports.ERC20Token__factory = exports.SignatureValidator__factory = exports.ReentrancyGuard__factory = exports.BalancesHelperV2__factory = exports.BalancesHelper__factory = exports.AccountRegistryMock__factory = exports.AccountImplementationV1Mock__factory = exports.AccountControllerMock__factory = exports.AccountRegistry__factory = exports.AccountImplementationV1__factory = exports.AccountController__factory = exports.AccountBase__factory = exports.Account__factory = exports.GuardedMock__factory = exports.Guarded__factory = exports.Controlled__factory = exports.LibDiamond__factory = exports.IStargateRouter__factory = exports.IStargateReceiver__factory = exports.IHopBridge__factory = exports.IERC173__factory = exports.IERC165__factory = exports.IDiamondLoupe__factory = exports.ICBridge__factory = void 0; var LPToken__factory_1 = require("./factories/LPToken__factory"); Object.defineProperty(exports, "LPToken__factory", { enumerable: true, get: function () { return LPToken__factory_1.LPToken__factory; } }); var IBridgeToken__factory_1 = require("./factories/IBridgeToken__factory"); @@ -172,6 +172,8 @@ var Gateway__factory_1 = require("./factories/Gateway__factory"); Object.defineProperty(exports, "Gateway__factory", { enumerable: true, get: function () { return Gateway__factory_1.Gateway__factory; } }); var GatewayRecipient__factory_1 = require("./factories/GatewayRecipient__factory"); Object.defineProperty(exports, "GatewayRecipient__factory", { enumerable: true, get: function () { return GatewayRecipient__factory_1.GatewayRecipient__factory; } }); +var GatewayV2__factory_1 = require("./factories/GatewayV2__factory"); +Object.defineProperty(exports, "GatewayV2__factory", { enumerable: true, get: function () { return GatewayV2__factory_1.GatewayV2__factory; } }); var GatewayRecipientMock__factory_1 = require("./factories/GatewayRecipientMock__factory"); Object.defineProperty(exports, "GatewayRecipientMock__factory", { enumerable: true, get: function () { return GatewayRecipientMock__factory_1.GatewayRecipientMock__factory; } }); var PaymentDepositAccount__factory_1 = require("./factories/PaymentDepositAccount__factory"); diff --git a/package-lock.json b/package-lock.json index 4e511297..fb79c3f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@etherspot/contracts", - "version": "1.9.0", + "version": "1.9.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@etherspot/contracts", - "version": "1.9.0", + "version": "1.9.2", "license": "MIT", "devDependencies": { "@connext/nxtp-contracts": "0.2.0-beta.20", diff --git a/package.json b/package.json index 9df544fc..de1a3f08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@etherspot/contracts", - "version": "1.9.1", + "version": "1.9.2", "description": "Etherspot Solidity contracts", "keywords": [ "ether", diff --git a/src/gateway/Gateway.sol b/src/gateway/Gateway.sol index ddaa72b5..5711c41c 100644 --- a/src/gateway/Gateway.sol +++ b/src/gateway/Gateway.sol @@ -437,4 +437,4 @@ contract Gateway is Initializable, SignatureValidator { return result; } -} +} \ No newline at end of file diff --git a/src/gateway/GatewayV2.sol b/src/gateway/GatewayV2.sol new file mode 100644 index 00000000..84faeaf1 --- /dev/null +++ b/src/gateway/GatewayV2.sol @@ -0,0 +1,554 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "../common/access/Guarded.sol"; +import "../common/libs/ECDSALib.sol"; +import "../common/libs/SafeMathLib.sol"; +import "../common/lifecycle/Initializable.sol"; +import "../common/signature/SignatureValidator.sol"; +import "../external/ExternalAccountRegistry.sol"; +import "../personal/PersonalAccountRegistry.sol"; + +/** + * @title Gateway V2 with guarded batching functions + * + * @notice GSN replacement + * + * @author Utkir Sobirov + */ +contract GatewayV2 is Initializable, SignatureValidator, Guarded { + using ECDSALib for bytes32; + using SafeMathLib for uint256; + + struct DelegatedBatch { + address account; + uint256 nonce; + address[] to; + bytes[] data; + } + + struct DelegatedBatchWithGasPrice { + address account; + uint256 nonce; + address[] to; + bytes[] data; + uint256 gasPrice; + } + + bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256( + "DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)" + ); + + bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256( + "DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)" + ); + + ExternalAccountRegistry public externalAccountRegistry; + PersonalAccountRegistry public personalAccountRegistry; + + mapping(address => uint256) private accountNonce; + + // events + + /** + * @dev Emitted when the single batch is delegated + * @param sender sender address + * @param batch batch + * @param succeeded if succeeded + */ + event BatchDelegated( + address sender, + bytes batch, + bool succeeded + ); + + /** + * @dev Public constructor + */ + constructor() public Initializable() SignatureValidator() {} + + // external functions + + /** + * @notice Initializes `Gateway` contract + * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address + * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address + */ + function initialize( + ExternalAccountRegistry externalAccountRegistry_, + PersonalAccountRegistry personalAccountRegistry_ + ) + external + onlyInitializer + { + externalAccountRegistry = externalAccountRegistry_; + personalAccountRegistry = personalAccountRegistry_; + + address[] memory guardians; + _initializeGuarded(guardians); // adds tx.origin to guardians list + } + + // public functions + + /** + * @notice Sends batch + * @dev `GatewayRecipient` context api: + * `_getContextAccount` will return `msg.sender` + * `_getContextSender` will return `msg.sender` + * + * @param to array of batch recipients contracts + * @param data array of batch data + */ + function sendBatch( + address[] memory to, + bytes[] memory data + ) + public + { + _sendBatch( + msg.sender, + msg.sender, + to, + data + ); + } + + /** + * @notice Sends guarded batch + * @dev `GatewayRecipient` context api: + * `_getContextAccount` will return `msg.sender` + * `_getContextSender` will return `msg.sender` + * + * @param to array of batch recipients contracts + * @param data array of batch data + */ + function sendBatchGuarded( + address[] memory to, + bytes[] memory data + ) + public + onlyGuardian + { + sendBatch(to, data); + } + + /** + * @notice Sends batch from the account + * @dev `GatewayRecipient` context api: + * `_getContextAccount` will return `account` arg + * `_getContextSender` will return `msg.sender` + * + * @param account account address + * @param to array of batch recipients contracts + * @param data array of batch data + */ + function sendBatchFromAccount( + address account, + address[] memory to, + bytes[] memory data + ) + public + { + _sendBatch( + account, + msg.sender, + to, + data + ); + } + + /** + * @notice Sends guarded batch from the account + * @dev `GatewayRecipient` context api: + * `_getContextAccount` will return `account` arg + * `_getContextSender` will return `msg.sender` + * + * @param account account address + * @param to array of batch recipients contracts + * @param data array of batch data + */ + function sendBatchFromAccountGuarded( + address account, + address[] memory to, + bytes[] memory data + ) + public + onlyGuardian + { + sendBatchFromAccount(account, to, data); + } + + /** + * @notice Delegates batch from the account + * @dev Use `hashDelegatedBatch` to create sender message payload. + * + * `GatewayRecipient` context api: + * `_getContextAccount` will return `account` arg + * `_getContextSender` will return recovered address from `senderSignature` arg + * + * @param account account address + * @param nonce next account nonce + * @param to array of batch recipients contracts + * @param data array of batch data + * @param senderSignature sender signature + */ + function delegateBatch( + address account, + uint256 nonce, + address[] memory to, + bytes[] memory data, + bytes memory senderSignature + ) + public + { + require( + nonce > accountNonce[account], + "Gateway: nonce is lower than current account nonce" + ); + + address sender = _hashDelegatedBatch( + account, + nonce, + to, + data + ).recoverAddress(senderSignature); + + accountNonce[account] = nonce; + + _sendBatch( + account, + sender, + to, + data + ); + } + + /** + * @notice Delegates guarded batch from the account + * @dev Use `hashDelegatedBatch` to create sender message payload. + * + * `GatewayRecipient` context api: + * `_getContextAccount` will return `account` arg + * `_getContextSender` will return recovered address from `senderSignature` arg + * + * @param account account address + * @param nonce next account nonce + * @param to array of batch recipients contracts + * @param data array of batch data + * @param senderSignature sender signature + */ + function delegateBatchGuarded( + address account, + uint256 nonce, + address[] memory to, + bytes[] memory data, + bytes memory senderSignature + ) + public + onlyGuardian + { + delegateBatch(account, nonce, to, data, senderSignature); + } + + /** + * @notice Delegates batch from the account (with gas price) + * + * @dev 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 + * + * @param account account address + * @param nonce next account nonce + * @param to array of batch recipients contracts + * @param data array of batch data + * @param senderSignature sender signature + */ + function delegateBatchWithGasPrice( + address account, + uint256 nonce, + address[] memory to, + bytes[] memory data, + bytes memory senderSignature + ) + public + { + require( + nonce > accountNonce[account], + "Gateway: nonce is lower than current account nonce" + ); + + address sender = _hashDelegatedBatchWithGasPrice( + account, + nonce, + to, + data, + tx.gasprice + ).recoverAddress(senderSignature); + + accountNonce[account] = nonce; + + _sendBatch( + account, + sender, + to, + data + ); + } + + /** + * @notice Delegates guarded batch from the account (with gas price) + * + * @dev 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 + * + * @param account account address + * @param nonce next account nonce + * @param to array of batch recipients contracts + * @param data array of batch data + * @param senderSignature sender signature + */ + function delegateBatchWithGasPriceGuarded( + address account, + uint256 nonce, + address[] memory to, + bytes[] memory data, + bytes memory senderSignature + ) + public + onlyGuardian + { + delegateBatchWithGasPrice(account, nonce, to, data, senderSignature); + } + + /** + * @notice Delegates multiple batches + * @dev It will revert when all batches fail + * @param batches array of batches + * @param revertOnFailure reverts on any error + */ + function delegateBatches( + bytes[] memory batches, + bool revertOnFailure + ) + public + { + require( + batches.length > 0, + "Gateway: cannot delegate empty batches" + ); + + bool anySucceeded; + + for (uint256 i = 0; i < batches.length; i++) { + // solhint-disable-next-line avoid-low-level-calls + (bool succeeded,) = address(this).call(batches[i]); + + if (revertOnFailure) { + require( + succeeded, + "Gateway: batch reverted" + ); + } else if (succeeded && !anySucceeded) { + anySucceeded = true; + } + + emit BatchDelegated( + msg.sender, + batches[i], + succeeded + ); + } + + if (!anySucceeded) { + revert("Gateway: all batches reverted"); + } + } + + /** + * @notice Delegates multiple guarded batches + * @dev It will revert when all batches fail + * @param batches array of batches + * @param revertOnFailure reverts on any error + */ + function delegateBatchesGuarded( + bytes[] memory batches, + bool revertOnFailure + ) + public + onlyGuardian + { + delegateBatches(batches, revertOnFailure); + } + + // public functions (views) + + /** + * @notice Hashes `DelegatedBatch` message payload + * @param delegatedBatch struct + * @return hash + */ + function hashDelegatedBatch( + DelegatedBatch memory delegatedBatch + ) + public + view + returns (bytes32) + { + return _hashDelegatedBatch( + delegatedBatch.account, + delegatedBatch.nonce, + delegatedBatch.to, + delegatedBatch.data + ); + } + + /** + * @notice Hashes `DelegatedBatchWithGasPrice` message payload + * @param delegatedBatch struct + * @return hash + */ + function hashDelegatedBatchWithGasPrice( + DelegatedBatchWithGasPrice memory delegatedBatch + ) + public + view + returns (bytes32) + { + return _hashDelegatedBatchWithGasPrice( + delegatedBatch.account, + delegatedBatch.nonce, + delegatedBatch.to, + delegatedBatch.data, + delegatedBatch.gasPrice + ); + } + + // external functions (views) + + /** + * @notice Gets next account nonce + * @param account account address + * @return next nonce + */ + function getAccountNextNonce( + address account + ) + external + view + returns (uint256) + { + return accountNonce[account].add(1); + } + + // private functions + + function _sendBatch( + address account, + address sender, + address[] memory to, + bytes[] memory data + ) + private + { + require( + account != address(0), + "Gateway: cannot send from 0x0 account" + ); + require( + to.length > 0, + "Gateway: cannot send empty batch" + ); + require( + data.length == to.length, + "Gateway: invalid batch" + ); + + if (account != sender) { + require( + personalAccountRegistry.verifyAccountOwner(account, sender) || + externalAccountRegistry.verifyAccountOwner(account, sender), + "Gateway: sender is not the account owner" + ); + } + + bool succeeded; + + for (uint256 i = 0; i < data.length; i++) { + require( + to[i] != address(0), + "Gateway: cannot send to 0x0" + ); + + // solhint-disable-next-line avoid-low-level-calls + (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender)); + + require( + succeeded, + "Gateway: batch transaction reverted" + ); + } + } + + // private functions (views) + + function _hashDelegatedBatch( + address account, + uint256 nonce, + address[] memory to, + bytes[] memory data + ) + private + view + returns (bytes32) + { + return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked( + account, + nonce, + to, + _concatBytes(data) + )); + } + + function _hashDelegatedBatchWithGasPrice( + address account, + uint256 nonce, + address[] memory to, + bytes[] memory data, + uint256 gasPrice + ) + private + view + returns (bytes32) + { + return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked( + account, + nonce, + to, + _concatBytes(data), + gasPrice + )); + } + +// private functions (pure) + + function _concatBytes(bytes[] memory data) + private + pure + returns (bytes memory) + { + bytes memory result; + uint dataLen = data.length; + + for (uint i = 0 ; i < dataLen ; i++) { + result = abi.encodePacked(result, data[i]); + } + + return result; + } +} diff --git a/test/bridges/HopFacet.ts b/test/bridges/HopFacet.ts index 8adca4e4..38f78d1e 100644 --- a/test/bridges/HopFacet.ts +++ b/test/bridges/HopFacet.ts @@ -8,7 +8,7 @@ import { } from '../shared'; import { HopConfig } from '../../config/hop'; -describe.only('HopFacet', () => { +describe('HopFacet', () => { describe("L1->L2", () => { const TEST_TOKEN_ADDRESS = '0x98339D8C260052B7ad81c28c16C0b98420f2B46a'; const SIGNER_ADDRESS = '0x03db1fa14c9d67a426d1d03514901fff08dc87cf'; diff --git a/test/gateway/Gateway.ts b/test/gateway/Gateway.ts index 218e1f65..0e424ccf 100644 --- a/test/gateway/Gateway.ts +++ b/test/gateway/Gateway.ts @@ -623,4 +623,4 @@ describe('Gateway', () => { ).resolves.toBeBN(1); }); }); -}); +}); \ No newline at end of file diff --git a/test/gateway/GatewayV2.ts b/test/gateway/GatewayV2.ts new file mode 100644 index 00000000..90d1fe4a --- /dev/null +++ b/test/gateway/GatewayV2.ts @@ -0,0 +1,981 @@ +import { deployments, ethers } from 'hardhat'; +import { BigNumberish, BytesLike } from 'ethers'; +import { + ExternalAccountRegistry, + GatewayV2, + GatewayRecipientMock, + PersonalAccountRegistry, +} from '../../typings'; +import { + GAS_PRICE, + SignerWithAddress, + createMessagePayloadFactory, + processTx, + randomAddress, + getNextNonce, + MessagePayloadFactory, + deployContract, +} from '../shared'; + +const { getSigners, getUnnamedSigners } = ethers; + +describe('GatewayV2', () => { + let signers: SignerWithAddress[]; + let deployer: SignerWithAddress; + let guardian: SignerWithAddress; + let externalAccountRegistry: ExternalAccountRegistry; + let gateway: GatewayV2; + let gatewayRecipientMock: GatewayRecipientMock; + let personalAccountRegistry: PersonalAccountRegistry; + + let to: string; + let data: string; + + let delegatedBatchMessagePayloadFactory: MessagePayloadFactory<{ + account: string; + nonce: BigNumberish; + to: string[]; + data: BytesLike[]; + }>; + let delegatedBatchWithGasPriceMessagePayloadFactory: MessagePayloadFactory<{ + account: string; + nonce: BigNumberish; + to: string[]; + data: BytesLike[]; + gasPrice: BigNumberish; + }>; + + before(async () => { + signers = [ + ...await getSigners(), + ...await getUnnamedSigners() + ]; // getSigners() returns only 20 signers + deployer = signers.shift(); + guardian = signers.pop(); + + await deployments.fixture([ + 'gateway', + 'gateway-v2', + 'external', + 'personal' + ]); + externalAccountRegistry = await ethers.getContract('ExternalAccountRegistry'); + personalAccountRegistry = await ethers.getContract('PersonalAccountRegistry'); + gateway = (await ethers.getContract('GatewayV2')).connect(deployer); + + gatewayRecipientMock = await deployContract('GatewayRecipientMock', [ + gateway.address, + ]); + + to = gatewayRecipientMock.address; + data = gatewayRecipientMock.interface.encodeFunctionData('emitContext'); + + delegatedBatchMessagePayloadFactory = createMessagePayloadFactory( + gateway, + 'DelegatedBatch', + [ + { + type: 'address', + name: 'account', + }, + { + type: 'uint256', + name: 'nonce', + }, + { + type: 'address[]', + name: 'to', + }, + { + type: 'bytes[]', + name: 'data', + }, + ], + ); + + delegatedBatchWithGasPriceMessagePayloadFactory = createMessagePayloadFactory( + gateway, + 'DelegatedBatchWithGasPrice', + [ + { + type: 'address', + name: 'account', + }, + { + type: 'uint256', + name: 'nonce', + }, + { + type: 'address[]', + name: 'to', + }, + { + type: 'bytes[]', + name: 'data', + }, + { + type: 'uint256', + name: 'gasPrice', + }, + ], + ); + }); + + context('guardians', () => { + let sender: SignerWithAddress; + + before(() => { + sender = signers.pop(); + gateway = gateway.connect(sender); + }); + + it('expect random address not to be guardian', async () => { + expect(await gateway.isGuardian(sender.address)).toBe(false); + expect(await gateway.isGuardian(deployer.address)).toBe(true); + }); + + it('expect random address to not be able to add guardian', async () => { + await expect(gateway.addGuardian(sender.address)) + .rejects + .toThrow(/Guarded: tx\.origin is not the guardian/); + }); + + it('expect to add guardian', async () => { + const { + logs: [log], + } = await processTx( + gateway.connect(deployer).addGuardian(guardian.address) + ); + + const event = gateway.interface.parseLog(log); + + expect(event.args.sender).toBe(deployer.address); + expect(event.args.guardian).toBe(guardian.address); + + expect(await gateway.isGuardian(guardian.address)).toBe(true); + }); + }); + + context('sendBatch()', () => { + let sender: SignerWithAddress; + + before(() => { + sender = signers.pop(); + gateway = gateway.connect(sender); + }); + + it('expect to send single call', async () => { + const { + logs: [log], + } = await processTx(gateway.sendBatch([to], [data])); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(sender.address); + expect(event.args.sender).toBe(sender.address); + }); + + it('expect to send multiple calls', async () => { + const { logs } = await processTx( + gateway.sendBatch([to, to], [data, data]), + ); + + const events = logs.map(log => + gatewayRecipientMock.interface.parseLog(log), + ); + + expect(events[0].args.account).toBe(sender.address); + expect(events[0].args.sender).toBe(sender.address); + expect(events[1].args.account).toBe(sender.address); + expect(events[1].args.sender).toBe(sender.address); + }); + }); + + context('sendBatchGuarded()', () => { + let sender: SignerWithAddress; + + before(() => { + sender = signers.pop(); + gateway = gateway.connect(sender); + }); + + it('expect to fail if sender is not guardian', async () => { + await expect(gateway.sendBatchGuarded([to], [data])) + .rejects + .toThrow(/Guarded: tx\.origin is not the guardian/); + }); + + it('expect to success if sender is guardian', async () => { + const { + logs: [log], + } = await processTx( + gateway + .connect(guardian) + .sendBatchGuarded([to], [data]) + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(guardian.address); + expect(event.args.sender).toBe(guardian.address); + }); + }); + + context('sendBatchFromAccount()', () => { + context('# account ownership stored in AccountOwnerRegistry', () => { + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(sender); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + }); + + it('expect to send single call', async () => { + const { + logs: [log], + } = await processTx( + gateway.sendBatchFromAccount(account.address, [to], [data]), + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(account.address); + expect(event.args.sender).toBe(sender.address); + }); + + it('expect to revert when sender is not an account owner', async () => { + const account = randomAddress(); + + await expect( + gateway.sendBatchFromAccount(account, [to], [data]), + ).rejects.toThrow(/revert/); + }); + }); + + context('# account ownership stored in PersonalAccountRegistry', () => { + let account: string; + let sender: SignerWithAddress; + + before(async () => { + sender = signers.pop(); + gateway = gateway.connect(sender); + account = await personalAccountRegistry.computeAccountAddress( + sender.address, + ); + }); + + it('expect to send single call', async () => { + const { + logs: [log], + } = await processTx( + gateway.sendBatchFromAccount(account, [to], [data]), + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(account); + expect(event.args.sender).toBe(sender.address); + }); + }); + }); + + context('sendBatchFromAccountGuarded()', () => { + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(sender); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(guardian.address), + ); + }); + + it('expect to fail if sender is not guardian', async () => { + await expect( + gateway.sendBatchFromAccountGuarded(account.address, [to], [data]) + ) + .rejects + .toThrow(/Guarded: tx\.origin is not the guardian/); + }); + + it('expect to success if sender is guardian', async () => { + const { + logs: [log], + } = await processTx( + gateway + .connect(guardian) + .sendBatchFromAccountGuarded(account.address, [to], [data]), + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(account.address); + expect(event.args.sender).toBe(guardian.address); + }); + }); + + context('delegateBatch()', () => { + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(signers.pop()); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + }); + + it('expect to send single call', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + const { + logs: [log], + } = await processTx( + gateway.delegateBatch( + account.address, + nonce, + [to], + [data], + senderSignature, + ), + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(account.address); + expect(event.args.sender).toBe(sender.address); + }); + + it('expect to revert on invalid signature', async () => { + const nonce = 0; // invalid nonce + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + await expect( + gateway.delegateBatch( + account.address, + nonce, + [to], + [data], + senderSignature, + ), + ).rejects.toThrow(/revert/); + }); + }); + + context('delegateBatchGuarded()', () => { + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(signers.pop()); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(guardian.address), + ); + }); + + it('expect to fail if sender is not guardian', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + await expect( + gateway.delegateBatchGuarded( + account.address, + nonce, + [to], + [data], + senderSignature, + ), + ) + .rejects + .toThrow(/Guarded: tx\.origin is not the guardian/); + }); + + it('expect to success if sender is guardian', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + const { + logs: [log], + } = await processTx( + gateway + .connect(guardian) + .delegateBatchGuarded( + account.address, + nonce, + [to], + [data], + senderSignature, + ), + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(account.address); + expect(event.args.sender).toBe(sender.address); + }); + }); + + context('delegateBatchWithGasPrice()', () => { + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(signers.pop()); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + }); + + it('expect to send single call', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchWithGasPriceMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + gasPrice: GAS_PRICE, + }, + ); + + const { + logs: [log], + } = await processTx( + gateway.delegateBatchWithGasPrice( + account.address, + nonce, + [to], + [data], + senderSignature, + { + gasPrice: GAS_PRICE, + }, + ), + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(account.address); + expect(event.args.sender).toBe(sender.address); + }); + }); + + context('delegateBatchWithGasPriceGuarded()', () => { + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(signers.pop()); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(guardian.address), + ); + }); + + it('expect to fail if sender is not guardian', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + await expect( + gateway.delegateBatchWithGasPriceGuarded( + account.address, + nonce, + [to], + [data], + senderSignature, + ), + ) + .rejects + .toThrow(/Guarded: tx\.origin is not the guardian/); + }); + + it('expect to success if sender is guardian', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchWithGasPriceMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + gasPrice: GAS_PRICE, + }, + ); + + const { + logs: [log], + } = await processTx( + gateway + .connect(guardian) + .delegateBatchWithGasPriceGuarded( + account.address, + nonce, + [to], + [data], + senderSignature, + { + gasPrice: GAS_PRICE, + }, + ), + ); + + const event = gatewayRecipientMock.interface.parseLog(log); + + expect(event.args.account).toBe(account.address); + expect(event.args.sender).toBe(sender.address); + }); + }); + + context('delegateBatches()', () => { + let from: SignerWithAddress; + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + from = signers.pop(); + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(from); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + }); + + it('expect to send single batch', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + const batch = gateway.interface.encodeFunctionData('delegateBatch', [ + account.address, + nonce, + [to], + [data], + senderSignature, + ]); + + const { events } = await processTx( + gateway.delegateBatches([batch], false), + ); + + const event = events.find(({ event }) => event === 'BatchDelegated'); + + expect(event.args.sender).toBe(from.address); + expect(event.args.batch).toBe(batch); + expect(event.args.succeeded).toBeTruthy(); + }); + + it('expect to send multiple batch', async () => { + const batches = []; + const batchesCount = 4; + + for (let index = 0; index < batchesCount; index += 1) { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + batches.push( + gateway.interface.encodeFunctionData('delegateBatch', [ + account.address, + nonce, + [to], + [data], + senderSignature, + ]), + ); + } + + let { events } = await processTx(gateway.delegateBatches(batches, false)); + + events = events.filter(({ event }) => event === 'BatchDelegated'); + + for (let index = 0; index < batchesCount; index += 1) { + expect(events[index].args.sender).toBe(from.address); + expect(events[index].args.batch).toBe(batches[index]); + expect(events[index].args.succeeded).toBeTruthy(); + } + }); + + it('expect to revert when all batches fails', async () => { + const batches = []; + const batchesCount = 4; + + for (let index = 0; index < batchesCount; index += 1) { + const nonce = 0; + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + batches.push( + gateway.interface.encodeFunctionData('delegateBatch', [ + account.address, + nonce, + [to], + [data], + senderSignature, + ]), + ); + } + + await expect(gateway.delegateBatches(batches, false)).rejects.toThrow( + /revert/, + ); + }); + + context('# revertOnFailure flag', () => { + const createBatches = async () => { + const result: string[] = []; + + const nonce = getNextNonce(); + + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + result.push( + gateway.interface.encodeFunctionData('delegateBatch', [ + account.address, + nonce, + [to], + [data], + senderSignature, + ]), + ); + + { + const nonce = 0; // invalid nonce + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + result.push( + gateway.interface.encodeFunctionData('delegateBatch', [ + account.address, + nonce, + [to], + [data], + senderSignature, + ]), + ); + } + + return result; + }; + + it('expect to revert on batch failure when revertOnFailure is set to true', async () => { + const batches = await createBatches(); + + await expect(gateway.delegateBatches(batches, true)).rejects.toThrow( + /revert/, + ); + }); + + it('expect to emit event when revertOnFailure is set to false', async () => { + const batches = await createBatches(); + + let { events } = await processTx( + gateway.delegateBatches(batches, false), + ); + + events = events.filter(({ event }) => event === 'BatchDelegated'); + + expect(events[0].args.sender).toBe(from.address); + expect(events[0].args.batch).toBe(batches[0]); + expect(events[0].args.succeeded).toBeTruthy(); + + expect(events[1].args.sender).toBe(from.address); + expect(events[1].args.batch).toBe(batches[1]); + expect(events[1].args.succeeded).toBeFalsy(); + }); + }); + }); + + context('delegateBatchesGuarded()', () => { + let from: SignerWithAddress; + let account: SignerWithAddress; + let sender: SignerWithAddress; + + before(async () => { + from = signers.pop(); + account = signers.pop(); + sender = signers.pop(); + gateway = gateway.connect(from); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(guardian.address), + ); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + }); + + it('expect to fail if sender is not guardian', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + const batch = gateway.interface.encodeFunctionData('delegateBatch', [ + account.address, + nonce, + [to], + [data], + senderSignature, + ]); + + await expect( + gateway.delegateBatchesGuarded([batch], false) + ) + .rejects + .toThrow(/Guarded: tx\.origin is not the guardian/); + }); + + it('expect to success if sender is guardian', async () => { + const nonce = getNextNonce(); + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + const batch = gateway.interface.encodeFunctionData('delegateBatch', [ + account.address, + nonce, + [to], + [data], + senderSignature, + ]); + + const { events } = await processTx( + gateway.connect(guardian).delegateBatchesGuarded([batch], false), + ); + + const event = events.find(({ event }) => event === 'BatchDelegated'); + + expect(event.args.sender).toBe(guardian.address); + expect(event.args.batch).toBe(batch); + expect(event.args.succeeded).toBeTruthy(); + }); + }); + + context('hashDelegatedBatch()', () => { + it('expect to return correct hash', async () => { + const message = { + account: randomAddress(), + nonce: 100, + to: [to], + data: [data], + }; + + const expected = delegatedBatchMessagePayloadFactory.hash(message); + + await expect(gateway.hashDelegatedBatch(message)).resolves.toBe(expected); + }); + }); + + context('hashDelegatedBatchWithGasPrice()', () => { + it('expect to return correct hash', async () => { + const message = { + account: randomAddress(), + nonce: 100, + to: [to], + data: [data], + gasPrice: GAS_PRICE, + }; + + const expected = delegatedBatchWithGasPriceMessagePayloadFactory.hash( + message, + ); + + await expect( + gateway.hashDelegatedBatchWithGasPrice(message), + ).resolves.toBe(expected); + }); + }); + + context('getAccountNextNonce()', () => { + let account: SignerWithAddress; + let nonce: number; + + before(async () => { + const sender = signers.pop(); + account = signers.pop(); + gateway = gateway.connect(signers.pop()); + + await processTx( + externalAccountRegistry + .connect(account) + .addAccountOwner(sender.address), + ); + nonce = getNextNonce(); + + const senderSignature = await delegatedBatchMessagePayloadFactory.sign( + sender, + { + account: account.address, + nonce, + to: [to], + data: [data], + }, + ); + + await processTx( + gateway.delegateBatch( + account.address, + nonce, + [to], + [data], + senderSignature, + ), + ); + }); + + it('expect to return correct nonce', async () => { + await expect( + gateway.getAccountNextNonce(account.address), + ).resolves.toBeBN(nonce + 1); + }); + + it('expect to return 1 for new account', async () => { + await expect( + gateway.getAccountNextNonce(randomAddress()), + ).resolves.toBeBN(1); + }); + }); +}); diff --git a/typings/AddressLib.ts b/typings/AddressLib.ts index 7d879ce6..2de864cf 100644 --- a/typings/AddressLib.ts +++ b/typings/AddressLib.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface AddressLibInterface extends utils.Interface { functions: { - "c_3858ce6a(bytes8)": FunctionFragment; - "c_false3858ce6a(bytes8)": FunctionFragment; - "c_true3858ce6a(bytes8)": FunctionFragment; + "c_6f8dca69(bytes8)": FunctionFragment; + "c_false6f8dca69(bytes8)": FunctionFragment; + "c_true6f8dca69(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_3858ce6a", + functionFragment: "c_6f8dca69", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_false3858ce6a", + functionFragment: "c_false6f8dca69", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_true3858ce6a", + functionFragment: "c_true6f8dca69", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_3858ce6a", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_6f8dca69", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_false3858ce6a", + functionFragment: "c_false6f8dca69", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_true3858ce6a", + functionFragment: "c_true6f8dca69", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface AddressLib extends BaseContract { removeListener: OnEvent; functions: { - c_3858ce6a( - c__3858ce6a: BytesLike, + c_6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_false3858ce6a( - c__3858ce6a: BytesLike, + c_false6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_true3858ce6a( - c__3858ce6a: BytesLike, + c_true6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_3858ce6a(c__3858ce6a: BytesLike, overrides?: CallOverrides): Promise; + c_6f8dca69(c__6f8dca69: BytesLike, overrides?: CallOverrides): Promise; - c_false3858ce6a( - c__3858ce6a: BytesLike, + c_false6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; - c_true3858ce6a( - c__3858ce6a: BytesLike, + c_true6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_3858ce6a( - c__3858ce6a: BytesLike, + c_6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; - c_false3858ce6a( - c__3858ce6a: BytesLike, + c_false6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; - c_true3858ce6a( - c__3858ce6a: BytesLike, + c_true6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface AddressLib extends BaseContract { filters: {}; estimateGas: { - c_3858ce6a( - c__3858ce6a: BytesLike, + c_6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; - c_false3858ce6a( - c__3858ce6a: BytesLike, + c_false6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; - c_true3858ce6a( - c__3858ce6a: BytesLike, + c_true6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_3858ce6a( - c__3858ce6a: BytesLike, + c_6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; - c_false3858ce6a( - c__3858ce6a: BytesLike, + c_false6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; - c_true3858ce6a( - c__3858ce6a: BytesLike, + c_true6f8dca69( + c__6f8dca69: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/BlockLib.ts b/typings/BlockLib.ts index 6fbb9501..79b2f9cf 100644 --- a/typings/BlockLib.ts +++ b/typings/BlockLib.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface BlockLibInterface extends utils.Interface { functions: { - "c_69b78653(bytes8)": FunctionFragment; - "c_false69b78653(bytes8)": FunctionFragment; - "c_true69b78653(bytes8)": FunctionFragment; + "c_e404c745(bytes8)": FunctionFragment; + "c_falsee404c745(bytes8)": FunctionFragment; + "c_truee404c745(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_69b78653", + functionFragment: "c_e404c745", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_false69b78653", + functionFragment: "c_falsee404c745", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_true69b78653", + functionFragment: "c_truee404c745", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_69b78653", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_e404c745", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_false69b78653", + functionFragment: "c_falsee404c745", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_true69b78653", + functionFragment: "c_truee404c745", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface BlockLib extends BaseContract { removeListener: OnEvent; functions: { - c_69b78653( - c__69b78653: BytesLike, + c_e404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_false69b78653( - c__69b78653: BytesLike, + c_falsee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_true69b78653( - c__69b78653: BytesLike, + c_truee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_69b78653(c__69b78653: BytesLike, overrides?: CallOverrides): Promise; + c_e404c745(c__e404c745: BytesLike, overrides?: CallOverrides): Promise; - c_false69b78653( - c__69b78653: BytesLike, + c_falsee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; - c_true69b78653( - c__69b78653: BytesLike, + c_truee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_69b78653( - c__69b78653: BytesLike, + c_e404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; - c_false69b78653( - c__69b78653: BytesLike, + c_falsee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; - c_true69b78653( - c__69b78653: BytesLike, + c_truee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface BlockLib extends BaseContract { filters: {}; estimateGas: { - c_69b78653( - c__69b78653: BytesLike, + c_e404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; - c_false69b78653( - c__69b78653: BytesLike, + c_falsee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; - c_true69b78653( - c__69b78653: BytesLike, + c_truee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_69b78653( - c__69b78653: BytesLike, + c_e404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; - c_false69b78653( - c__69b78653: BytesLike, + c_falsee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; - c_true69b78653( - c__69b78653: BytesLike, + c_truee404c745( + c__e404c745: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/BytesLib.ts b/typings/BytesLib.ts index 0b6abcd4..f70dc2a1 100644 --- a/typings/BytesLib.ts +++ b/typings/BytesLib.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface BytesLibInterface extends utils.Interface { functions: { - "c_374166e6(bytes8)": FunctionFragment; - "c_false374166e6(bytes8)": FunctionFragment; - "c_true374166e6(bytes8)": FunctionFragment; + "c_72a5b528(bytes8)": FunctionFragment; + "c_false72a5b528(bytes8)": FunctionFragment; + "c_true72a5b528(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_374166e6", + functionFragment: "c_72a5b528", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_false374166e6", + functionFragment: "c_false72a5b528", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_true374166e6", + functionFragment: "c_true72a5b528", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_374166e6", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_72a5b528", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_false374166e6", + functionFragment: "c_false72a5b528", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_true374166e6", + functionFragment: "c_true72a5b528", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface BytesLib extends BaseContract { removeListener: OnEvent; functions: { - c_374166e6( - c__374166e6: BytesLike, + c_72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_false374166e6( - c__374166e6: BytesLike, + c_false72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_true374166e6( - c__374166e6: BytesLike, + c_true72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_374166e6(c__374166e6: BytesLike, overrides?: CallOverrides): Promise; + c_72a5b528(c__72a5b528: BytesLike, overrides?: CallOverrides): Promise; - c_false374166e6( - c__374166e6: BytesLike, + c_false72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; - c_true374166e6( - c__374166e6: BytesLike, + c_true72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_374166e6( - c__374166e6: BytesLike, + c_72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; - c_false374166e6( - c__374166e6: BytesLike, + c_false72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; - c_true374166e6( - c__374166e6: BytesLike, + c_true72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface BytesLib extends BaseContract { filters: {}; estimateGas: { - c_374166e6( - c__374166e6: BytesLike, + c_72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; - c_false374166e6( - c__374166e6: BytesLike, + c_false72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; - c_true374166e6( - c__374166e6: BytesLike, + c_true72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_374166e6( - c__374166e6: BytesLike, + c_72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; - c_false374166e6( - c__374166e6: BytesLike, + c_false72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; - c_true374166e6( - c__374166e6: BytesLike, + c_true72a5b528( + c__72a5b528: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/ECDSAExtendedLib.ts b/typings/ECDSAExtendedLib.ts index b1460862..f4c318b2 100644 --- a/typings/ECDSAExtendedLib.ts +++ b/typings/ECDSAExtendedLib.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface ECDSAExtendedLibInterface extends utils.Interface { functions: { - "c_02b1372d(bytes8)": FunctionFragment; - "c_false02b1372d(bytes8)": FunctionFragment; - "c_true02b1372d(bytes8)": FunctionFragment; + "c_81f5e90e(bytes8)": FunctionFragment; + "c_false81f5e90e(bytes8)": FunctionFragment; + "c_true81f5e90e(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_02b1372d", + functionFragment: "c_81f5e90e", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_false02b1372d", + functionFragment: "c_false81f5e90e", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_true02b1372d", + functionFragment: "c_true81f5e90e", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_02b1372d", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_81f5e90e", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_false02b1372d", + functionFragment: "c_false81f5e90e", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_true02b1372d", + functionFragment: "c_true81f5e90e", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface ECDSAExtendedLib extends BaseContract { removeListener: OnEvent; functions: { - c_02b1372d( - c__02b1372d: BytesLike, + c_81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_false02b1372d( - c__02b1372d: BytesLike, + c_false81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_true02b1372d( - c__02b1372d: BytesLike, + c_true81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_02b1372d(c__02b1372d: BytesLike, overrides?: CallOverrides): Promise; + c_81f5e90e(c__81f5e90e: BytesLike, overrides?: CallOverrides): Promise; - c_false02b1372d( - c__02b1372d: BytesLike, + c_false81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; - c_true02b1372d( - c__02b1372d: BytesLike, + c_true81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_02b1372d( - c__02b1372d: BytesLike, + c_81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; - c_false02b1372d( - c__02b1372d: BytesLike, + c_false81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; - c_true02b1372d( - c__02b1372d: BytesLike, + c_true81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface ECDSAExtendedLib extends BaseContract { filters: {}; estimateGas: { - c_02b1372d( - c__02b1372d: BytesLike, + c_81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; - c_false02b1372d( - c__02b1372d: BytesLike, + c_false81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; - c_true02b1372d( - c__02b1372d: BytesLike, + c_true81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_02b1372d( - c__02b1372d: BytesLike, + c_81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; - c_false02b1372d( - c__02b1372d: BytesLike, + c_false81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; - c_true02b1372d( - c__02b1372d: BytesLike, + c_true81f5e90e( + c__81f5e90e: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/ECDSALib.ts b/typings/ECDSALib.ts index 8c5ac264..4befd286 100644 --- a/typings/ECDSALib.ts +++ b/typings/ECDSALib.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface ECDSALibInterface extends utils.Interface { functions: { - "c_b0cf6ac1(bytes8)": FunctionFragment; - "c_falseb0cf6ac1(bytes8)": FunctionFragment; - "c_trueb0cf6ac1(bytes8)": FunctionFragment; + "c_34283de1(bytes8)": FunctionFragment; + "c_false34283de1(bytes8)": FunctionFragment; + "c_true34283de1(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_b0cf6ac1", + functionFragment: "c_34283de1", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_falseb0cf6ac1", + functionFragment: "c_false34283de1", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_trueb0cf6ac1", + functionFragment: "c_true34283de1", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_b0cf6ac1", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_34283de1", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_falseb0cf6ac1", + functionFragment: "c_false34283de1", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_trueb0cf6ac1", + functionFragment: "c_true34283de1", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface ECDSALib extends BaseContract { removeListener: OnEvent; functions: { - c_b0cf6ac1( - c__b0cf6ac1: BytesLike, + c_34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_falseb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_false34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_trueb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_true34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_b0cf6ac1(c__b0cf6ac1: BytesLike, overrides?: CallOverrides): Promise; + c_34283de1(c__34283de1: BytesLike, overrides?: CallOverrides): Promise; - c_falseb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_false34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_true34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_b0cf6ac1( - c__b0cf6ac1: BytesLike, + c_34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; - c_falseb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_false34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_true34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface ECDSALib extends BaseContract { filters: {}; estimateGas: { - c_b0cf6ac1( - c__b0cf6ac1: BytesLike, + c_34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; - c_falseb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_false34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_true34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_b0cf6ac1( - c__b0cf6ac1: BytesLike, + c_34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; - c_falseb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_false34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb0cf6ac1( - c__b0cf6ac1: BytesLike, + c_true34283de1( + c__34283de1: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/ENSAbstractResolver.ts b/typings/ENSAbstractResolver.ts index 43efc000..7e5d5f25 100644 --- a/typings/ENSAbstractResolver.ts +++ b/typings/ENSAbstractResolver.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface ENSAbstractResolverInterface extends utils.Interface { functions: { - "c_ac93193e(bytes8)": FunctionFragment; - "c_falseac93193e(bytes8)": FunctionFragment; - "c_trueac93193e(bytes8)": FunctionFragment; + "c_96741811(bytes8)": FunctionFragment; + "c_false96741811(bytes8)": FunctionFragment; + "c_true96741811(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_ac93193e", + functionFragment: "c_96741811", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_falseac93193e", + functionFragment: "c_false96741811", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_trueac93193e", + functionFragment: "c_true96741811", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_ac93193e", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_96741811", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_falseac93193e", + functionFragment: "c_false96741811", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_trueac93193e", + functionFragment: "c_true96741811", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface ENSAbstractResolver extends BaseContract { removeListener: OnEvent; functions: { - c_ac93193e( - c__ac93193e: BytesLike, + c_96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_falseac93193e( - c__ac93193e: BytesLike, + c_false96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_trueac93193e( - c__ac93193e: BytesLike, + c_true96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_ac93193e(c__ac93193e: BytesLike, overrides?: CallOverrides): Promise; + c_96741811(c__96741811: BytesLike, overrides?: CallOverrides): Promise; - c_falseac93193e( - c__ac93193e: BytesLike, + c_false96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; - c_trueac93193e( - c__ac93193e: BytesLike, + c_true96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_ac93193e( - c__ac93193e: BytesLike, + c_96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; - c_falseac93193e( - c__ac93193e: BytesLike, + c_false96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; - c_trueac93193e( - c__ac93193e: BytesLike, + c_true96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface ENSAbstractResolver extends BaseContract { filters: {}; estimateGas: { - c_ac93193e( - c__ac93193e: BytesLike, + c_96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; - c_falseac93193e( - c__ac93193e: BytesLike, + c_false96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; - c_trueac93193e( - c__ac93193e: BytesLike, + c_true96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_ac93193e( - c__ac93193e: BytesLike, + c_96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; - c_falseac93193e( - c__ac93193e: BytesLike, + c_false96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; - c_trueac93193e( - c__ac93193e: BytesLike, + c_true96741811( + c__96741811: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/GatewayV2.ts b/typings/GatewayV2.ts new file mode 100644 index 00000000..4fcc47c8 --- /dev/null +++ b/typings/GatewayV2.ts @@ -0,0 +1,944 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { + BaseContract, + BigNumber, + BigNumberish, + BytesLike, + CallOverrides, + ContractTransaction, + Overrides, + PopulatedTransaction, + Signer, + utils, +} from "ethers"; +import { FunctionFragment, Result, EventFragment } from "@ethersproject/abi"; +import { Listener, Provider } from "@ethersproject/providers"; +import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; + +export type DelegatedBatchStruct = { + account: string; + nonce: BigNumberish; + to: string[]; + data: BytesLike[]; +}; + +export type DelegatedBatchStructOutput = [ + string, + BigNumber, + string[], + string[] +] & { account: string; nonce: BigNumber; to: string[]; data: string[] }; + +export type DelegatedBatchWithGasPriceStruct = { + account: string; + nonce: BigNumberish; + to: string[]; + data: BytesLike[]; + gasPrice: BigNumberish; +}; + +export type DelegatedBatchWithGasPriceStructOutput = [ + string, + BigNumber, + string[], + string[], + BigNumber +] & { + account: string; + nonce: BigNumber; + to: string[]; + data: string[]; + gasPrice: BigNumber; +}; + +export interface GatewayV2Interface extends utils.Interface { + functions: { + "addGuardian(address)": FunctionFragment; + "chainId()": FunctionFragment; + "delegateBatch(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatchGuarded(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatchWithGasPriceGuarded(address,uint256,address[],bytes[],bytes)": FunctionFragment; + "delegateBatches(bytes[],bool)": FunctionFragment; + "delegateBatchesGuarded(bytes[],bool)": FunctionFragment; + "externalAccountRegistry()": FunctionFragment; + "getAccountNextNonce(address)": FunctionFragment; + "hashDelegatedBatch((address,uint256,address[],bytes[]))": FunctionFragment; + "hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))": FunctionFragment; + "initialize(address,address)": FunctionFragment; + "isGuardian(address)": FunctionFragment; + "isInitialized()": FunctionFragment; + "personalAccountRegistry()": FunctionFragment; + "removeGuardian(address)": FunctionFragment; + "sendBatch(address[],bytes[])": FunctionFragment; + "sendBatchFromAccount(address,address[],bytes[])": FunctionFragment; + "sendBatchFromAccountGuarded(address,address[],bytes[])": FunctionFragment; + "sendBatchGuarded(address[],bytes[])": FunctionFragment; + "verifyGuardianSignature(bytes32,bytes)": FunctionFragment; + }; + + encodeFunctionData(functionFragment: "addGuardian", values: [string]): string; + encodeFunctionData(functionFragment: "chainId", values?: undefined): string; + encodeFunctionData( + functionFragment: "delegateBatch", + values: [string, BigNumberish, string[], BytesLike[], BytesLike] + ): string; + encodeFunctionData( + functionFragment: "delegateBatchGuarded", + values: [string, BigNumberish, string[], BytesLike[], BytesLike] + ): string; + encodeFunctionData( + functionFragment: "delegateBatchWithGasPrice", + values: [string, BigNumberish, string[], BytesLike[], BytesLike] + ): string; + encodeFunctionData( + functionFragment: "delegateBatchWithGasPriceGuarded", + values: [string, BigNumberish, string[], BytesLike[], BytesLike] + ): string; + encodeFunctionData( + functionFragment: "delegateBatches", + values: [BytesLike[], boolean] + ): string; + encodeFunctionData( + functionFragment: "delegateBatchesGuarded", + values: [BytesLike[], boolean] + ): string; + encodeFunctionData( + functionFragment: "externalAccountRegistry", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "getAccountNextNonce", + values: [string] + ): string; + encodeFunctionData( + functionFragment: "hashDelegatedBatch", + values: [DelegatedBatchStruct] + ): string; + encodeFunctionData( + functionFragment: "hashDelegatedBatchWithGasPrice", + values: [DelegatedBatchWithGasPriceStruct] + ): string; + encodeFunctionData( + functionFragment: "initialize", + values: [string, string] + ): string; + encodeFunctionData(functionFragment: "isGuardian", values: [string]): string; + encodeFunctionData( + functionFragment: "isInitialized", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "personalAccountRegistry", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "removeGuardian", + values: [string] + ): string; + encodeFunctionData( + functionFragment: "sendBatch", + values: [string[], BytesLike[]] + ): string; + encodeFunctionData( + functionFragment: "sendBatchFromAccount", + values: [string, string[], BytesLike[]] + ): string; + encodeFunctionData( + functionFragment: "sendBatchFromAccountGuarded", + values: [string, string[], BytesLike[]] + ): string; + encodeFunctionData( + functionFragment: "sendBatchGuarded", + values: [string[], BytesLike[]] + ): string; + encodeFunctionData( + functionFragment: "verifyGuardianSignature", + values: [BytesLike, BytesLike] + ): string; + + decodeFunctionResult( + functionFragment: "addGuardian", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "chainId", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "delegateBatch", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "delegateBatchGuarded", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "delegateBatchWithGasPrice", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "delegateBatchWithGasPriceGuarded", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "delegateBatches", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "delegateBatchesGuarded", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "externalAccountRegistry", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getAccountNextNonce", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "hashDelegatedBatch", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "hashDelegatedBatchWithGasPrice", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "initialize", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "isGuardian", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "isInitialized", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "personalAccountRegistry", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "removeGuardian", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "sendBatch", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "sendBatchFromAccount", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "sendBatchFromAccountGuarded", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "sendBatchGuarded", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "verifyGuardianSignature", + data: BytesLike + ): Result; + + events: { + "BatchDelegated(address,bytes,bool)": EventFragment; + "GuardianAdded(address,address)": EventFragment; + "GuardianRemoved(address,address)": EventFragment; + "Initialized(address)": EventFragment; + }; + + getEvent(nameOrSignatureOrTopic: "BatchDelegated"): EventFragment; + getEvent(nameOrSignatureOrTopic: "GuardianAdded"): EventFragment; + getEvent(nameOrSignatureOrTopic: "GuardianRemoved"): EventFragment; + getEvent(nameOrSignatureOrTopic: "Initialized"): EventFragment; +} + +export type BatchDelegatedEvent = TypedEvent< + [string, string, boolean], + { sender: string; batch: string; succeeded: boolean } +>; + +export type BatchDelegatedEventFilter = TypedEventFilter; + +export type GuardianAddedEvent = TypedEvent< + [string, string], + { sender: string; guardian: string } +>; + +export type GuardianAddedEventFilter = TypedEventFilter; + +export type GuardianRemovedEvent = TypedEvent< + [string, string], + { sender: string; guardian: string } +>; + +export type GuardianRemovedEventFilter = TypedEventFilter; + +export type InitializedEvent = TypedEvent<[string], { initializer: string }>; + +export type InitializedEventFilter = TypedEventFilter; + +export interface GatewayV2 extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + interface: GatewayV2Interface; + + queryFilter( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>; + + listeners( + eventFilter?: TypedEventFilter + ): Array>; + listeners(eventName?: string): Array; + removeAllListeners( + eventFilter: TypedEventFilter + ): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + + functions: { + addGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + chainId(overrides?: CallOverrides): Promise<[BigNumber]>; + + delegateBatch( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPrice( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPriceGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatches( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchesGuarded( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + externalAccountRegistry(overrides?: CallOverrides): Promise<[string]>; + + getAccountNextNonce( + account: string, + overrides?: CallOverrides + ): Promise<[BigNumber]>; + + hashDelegatedBatch( + delegatedBatch: DelegatedBatchStruct, + overrides?: CallOverrides + ): Promise<[string]>; + + hashDelegatedBatchWithGasPrice( + delegatedBatch: DelegatedBatchWithGasPriceStruct, + overrides?: CallOverrides + ): Promise<[string]>; + + initialize( + externalAccountRegistry_: string, + personalAccountRegistry_: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + isGuardian(guardian: string, overrides?: CallOverrides): Promise<[boolean]>; + + isInitialized(overrides?: CallOverrides): Promise<[boolean]>; + + personalAccountRegistry(overrides?: CallOverrides): Promise<[string]>; + + removeGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatch( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccount( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccountGuarded( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchGuarded( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + verifyGuardianSignature( + messageHash: BytesLike, + signature: BytesLike, + overrides?: CallOverrides + ): Promise<[boolean]>; + }; + + addGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + chainId(overrides?: CallOverrides): Promise; + + delegateBatch( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPrice( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPriceGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatches( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchesGuarded( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + externalAccountRegistry(overrides?: CallOverrides): Promise; + + getAccountNextNonce( + account: string, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatch( + delegatedBatch: DelegatedBatchStruct, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatchWithGasPrice( + delegatedBatch: DelegatedBatchWithGasPriceStruct, + overrides?: CallOverrides + ): Promise; + + initialize( + externalAccountRegistry_: string, + personalAccountRegistry_: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + isGuardian(guardian: string, overrides?: CallOverrides): Promise; + + isInitialized(overrides?: CallOverrides): Promise; + + personalAccountRegistry(overrides?: CallOverrides): Promise; + + removeGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatch( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccount( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccountGuarded( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchGuarded( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + verifyGuardianSignature( + messageHash: BytesLike, + signature: BytesLike, + overrides?: CallOverrides + ): Promise; + + callStatic: { + addGuardian(guardian: string, overrides?: CallOverrides): Promise; + + chainId(overrides?: CallOverrides): Promise; + + delegateBatch( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: CallOverrides + ): Promise; + + delegateBatchGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: CallOverrides + ): Promise; + + delegateBatchWithGasPrice( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: CallOverrides + ): Promise; + + delegateBatchWithGasPriceGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: CallOverrides + ): Promise; + + delegateBatches( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: CallOverrides + ): Promise; + + delegateBatchesGuarded( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: CallOverrides + ): Promise; + + externalAccountRegistry(overrides?: CallOverrides): Promise; + + getAccountNextNonce( + account: string, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatch( + delegatedBatch: DelegatedBatchStruct, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatchWithGasPrice( + delegatedBatch: DelegatedBatchWithGasPriceStruct, + overrides?: CallOverrides + ): Promise; + + initialize( + externalAccountRegistry_: string, + personalAccountRegistry_: string, + overrides?: CallOverrides + ): Promise; + + isGuardian(guardian: string, overrides?: CallOverrides): Promise; + + isInitialized(overrides?: CallOverrides): Promise; + + personalAccountRegistry(overrides?: CallOverrides): Promise; + + removeGuardian(guardian: string, overrides?: CallOverrides): Promise; + + sendBatch( + to: string[], + data: BytesLike[], + overrides?: CallOverrides + ): Promise; + + sendBatchFromAccount( + account: string, + to: string[], + data: BytesLike[], + overrides?: CallOverrides + ): Promise; + + sendBatchFromAccountGuarded( + account: string, + to: string[], + data: BytesLike[], + overrides?: CallOverrides + ): Promise; + + sendBatchGuarded( + to: string[], + data: BytesLike[], + overrides?: CallOverrides + ): Promise; + + verifyGuardianSignature( + messageHash: BytesLike, + signature: BytesLike, + overrides?: CallOverrides + ): Promise; + }; + + filters: { + "BatchDelegated(address,bytes,bool)"( + sender?: null, + batch?: null, + succeeded?: null + ): BatchDelegatedEventFilter; + BatchDelegated( + sender?: null, + batch?: null, + succeeded?: null + ): BatchDelegatedEventFilter; + + "GuardianAdded(address,address)"( + sender?: null, + guardian?: null + ): GuardianAddedEventFilter; + GuardianAdded(sender?: null, guardian?: null): GuardianAddedEventFilter; + + "GuardianRemoved(address,address)"( + sender?: null, + guardian?: null + ): GuardianRemovedEventFilter; + GuardianRemoved(sender?: null, guardian?: null): GuardianRemovedEventFilter; + + "Initialized(address)"(initializer?: null): InitializedEventFilter; + Initialized(initializer?: null): InitializedEventFilter; + }; + + estimateGas: { + addGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + chainId(overrides?: CallOverrides): Promise; + + delegateBatch( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPrice( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPriceGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatches( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchesGuarded( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + externalAccountRegistry(overrides?: CallOverrides): Promise; + + getAccountNextNonce( + account: string, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatch( + delegatedBatch: DelegatedBatchStruct, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatchWithGasPrice( + delegatedBatch: DelegatedBatchWithGasPriceStruct, + overrides?: CallOverrides + ): Promise; + + initialize( + externalAccountRegistry_: string, + personalAccountRegistry_: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + isGuardian(guardian: string, overrides?: CallOverrides): Promise; + + isInitialized(overrides?: CallOverrides): Promise; + + personalAccountRegistry(overrides?: CallOverrides): Promise; + + removeGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatch( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccount( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccountGuarded( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchGuarded( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + verifyGuardianSignature( + messageHash: BytesLike, + signature: BytesLike, + overrides?: CallOverrides + ): Promise; + }; + + populateTransaction: { + addGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + chainId(overrides?: CallOverrides): Promise; + + delegateBatch( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPrice( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchWithGasPriceGuarded( + account: string, + nonce: BigNumberish, + to: string[], + data: BytesLike[], + senderSignature: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatches( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + delegateBatchesGuarded( + batches: BytesLike[], + revertOnFailure: boolean, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + externalAccountRegistry( + overrides?: CallOverrides + ): Promise; + + getAccountNextNonce( + account: string, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatch( + delegatedBatch: DelegatedBatchStruct, + overrides?: CallOverrides + ): Promise; + + hashDelegatedBatchWithGasPrice( + delegatedBatch: DelegatedBatchWithGasPriceStruct, + overrides?: CallOverrides + ): Promise; + + initialize( + externalAccountRegistry_: string, + personalAccountRegistry_: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + isGuardian( + guardian: string, + overrides?: CallOverrides + ): Promise; + + isInitialized(overrides?: CallOverrides): Promise; + + personalAccountRegistry( + overrides?: CallOverrides + ): Promise; + + removeGuardian( + guardian: string, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatch( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccount( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchFromAccountGuarded( + account: string, + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + sendBatchGuarded( + to: string[], + data: BytesLike[], + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + verifyGuardianSignature( + messageHash: BytesLike, + signature: BytesLike, + overrides?: CallOverrides + ): Promise; + }; +} diff --git a/typings/LibAsset.ts b/typings/LibAsset.ts index d90edc4e..3b00a88a 100644 --- a/typings/LibAsset.ts +++ b/typings/LibAsset.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface LibAssetInterface extends utils.Interface { functions: { - "c_61c7bb39(bytes8)": FunctionFragment; - "c_false61c7bb39(bytes8)": FunctionFragment; - "c_true61c7bb39(bytes8)": FunctionFragment; + "c_ba3e7152(bytes8)": FunctionFragment; + "c_falseba3e7152(bytes8)": FunctionFragment; + "c_trueba3e7152(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_61c7bb39", + functionFragment: "c_ba3e7152", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_false61c7bb39", + functionFragment: "c_falseba3e7152", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_true61c7bb39", + functionFragment: "c_trueba3e7152", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_61c7bb39", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_ba3e7152", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_false61c7bb39", + functionFragment: "c_falseba3e7152", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_true61c7bb39", + functionFragment: "c_trueba3e7152", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface LibAsset extends BaseContract { removeListener: OnEvent; functions: { - c_61c7bb39( - c__61c7bb39: BytesLike, + c_ba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_false61c7bb39( - c__61c7bb39: BytesLike, + c_falseba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_true61c7bb39( - c__61c7bb39: BytesLike, + c_trueba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_61c7bb39(c__61c7bb39: BytesLike, overrides?: CallOverrides): Promise; + c_ba3e7152(c__ba3e7152: BytesLike, overrides?: CallOverrides): Promise; - c_false61c7bb39( - c__61c7bb39: BytesLike, + c_falseba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; - c_true61c7bb39( - c__61c7bb39: BytesLike, + c_trueba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_61c7bb39( - c__61c7bb39: BytesLike, + c_ba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; - c_false61c7bb39( - c__61c7bb39: BytesLike, + c_falseba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; - c_true61c7bb39( - c__61c7bb39: BytesLike, + c_trueba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface LibAsset extends BaseContract { filters: {}; estimateGas: { - c_61c7bb39( - c__61c7bb39: BytesLike, + c_ba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; - c_false61c7bb39( - c__61c7bb39: BytesLike, + c_falseba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; - c_true61c7bb39( - c__61c7bb39: BytesLike, + c_trueba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_61c7bb39( - c__61c7bb39: BytesLike, + c_ba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; - c_false61c7bb39( - c__61c7bb39: BytesLike, + c_falseba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; - c_true61c7bb39( - c__61c7bb39: BytesLike, + c_trueba3e7152( + c__ba3e7152: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/SafeMathLib.ts b/typings/SafeMathLib.ts index 1b7e73ce..34dbb494 100644 --- a/typings/SafeMathLib.ts +++ b/typings/SafeMathLib.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface SafeMathLibInterface extends utils.Interface { functions: { - "c_60aa1e30(bytes8)": FunctionFragment; - "c_false60aa1e30(bytes8)": FunctionFragment; - "c_true60aa1e30(bytes8)": FunctionFragment; + "c_7fef3447(bytes8)": FunctionFragment; + "c_false7fef3447(bytes8)": FunctionFragment; + "c_true7fef3447(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_60aa1e30", + functionFragment: "c_7fef3447", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_false60aa1e30", + functionFragment: "c_false7fef3447", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_true60aa1e30", + functionFragment: "c_true7fef3447", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_60aa1e30", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_7fef3447", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_false60aa1e30", + functionFragment: "c_false7fef3447", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_true60aa1e30", + functionFragment: "c_true7fef3447", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface SafeMathLib extends BaseContract { removeListener: OnEvent; functions: { - c_60aa1e30( - c__60aa1e30: BytesLike, + c_7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_false60aa1e30( - c__60aa1e30: BytesLike, + c_false7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_true60aa1e30( - c__60aa1e30: BytesLike, + c_true7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_60aa1e30(c__60aa1e30: BytesLike, overrides?: CallOverrides): Promise; + c_7fef3447(c__7fef3447: BytesLike, overrides?: CallOverrides): Promise; - c_false60aa1e30( - c__60aa1e30: BytesLike, + c_false7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; - c_true60aa1e30( - c__60aa1e30: BytesLike, + c_true7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_60aa1e30( - c__60aa1e30: BytesLike, + c_7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; - c_false60aa1e30( - c__60aa1e30: BytesLike, + c_false7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; - c_true60aa1e30( - c__60aa1e30: BytesLike, + c_true7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface SafeMathLib extends BaseContract { filters: {}; estimateGas: { - c_60aa1e30( - c__60aa1e30: BytesLike, + c_7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; - c_false60aa1e30( - c__60aa1e30: BytesLike, + c_false7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; - c_true60aa1e30( - c__60aa1e30: BytesLike, + c_true7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_60aa1e30( - c__60aa1e30: BytesLike, + c_7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; - c_false60aa1e30( - c__60aa1e30: BytesLike, + c_false7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; - c_true60aa1e30( - c__60aa1e30: BytesLike, + c_true7fef3447( + c__7fef3447: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/StringsLib.ts b/typings/StringsLib.ts index 52f8c6fc..d59821e3 100644 --- a/typings/StringsLib.ts +++ b/typings/StringsLib.ts @@ -16,31 +16,31 @@ import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; export interface StringsLibInterface extends utils.Interface { functions: { - "c_b490eebc(bytes8)": FunctionFragment; - "c_falseb490eebc(bytes8)": FunctionFragment; - "c_trueb490eebc(bytes8)": FunctionFragment; + "c_bf28adcf(bytes8)": FunctionFragment; + "c_falsebf28adcf(bytes8)": FunctionFragment; + "c_truebf28adcf(bytes8)": FunctionFragment; }; encodeFunctionData( - functionFragment: "c_b490eebc", + functionFragment: "c_bf28adcf", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_falseb490eebc", + functionFragment: "c_falsebf28adcf", values: [BytesLike] ): string; encodeFunctionData( - functionFragment: "c_trueb490eebc", + functionFragment: "c_truebf28adcf", values: [BytesLike] ): string; - decodeFunctionResult(functionFragment: "c_b490eebc", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "c_bf28adcf", data: BytesLike): Result; decodeFunctionResult( - functionFragment: "c_falseb490eebc", + functionFragment: "c_falsebf28adcf", data: BytesLike ): Result; decodeFunctionResult( - functionFragment: "c_trueb490eebc", + functionFragment: "c_truebf28adcf", data: BytesLike ): Result; @@ -74,47 +74,47 @@ export interface StringsLib extends BaseContract { removeListener: OnEvent; functions: { - c_b490eebc( - c__b490eebc: BytesLike, + c_bf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise<[void]>; - c_falseb490eebc( - c__b490eebc: BytesLike, + c_falsebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; - c_trueb490eebc( - c__b490eebc: BytesLike, + c_truebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise<[boolean]>; }; - c_b490eebc(c__b490eebc: BytesLike, overrides?: CallOverrides): Promise; + c_bf28adcf(c__bf28adcf: BytesLike, overrides?: CallOverrides): Promise; - c_falseb490eebc( - c__b490eebc: BytesLike, + c_falsebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb490eebc( - c__b490eebc: BytesLike, + c_truebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; callStatic: { - c_b490eebc( - c__b490eebc: BytesLike, + c_bf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; - c_falseb490eebc( - c__b490eebc: BytesLike, + c_falsebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb490eebc( - c__b490eebc: BytesLike, + c_truebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; }; @@ -122,35 +122,35 @@ export interface StringsLib extends BaseContract { filters: {}; estimateGas: { - c_b490eebc( - c__b490eebc: BytesLike, + c_bf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; - c_falseb490eebc( - c__b490eebc: BytesLike, + c_falsebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb490eebc( - c__b490eebc: BytesLike, + c_truebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; }; populateTransaction: { - c_b490eebc( - c__b490eebc: BytesLike, + c_bf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; - c_falseb490eebc( - c__b490eebc: BytesLike, + c_falsebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; - c_trueb490eebc( - c__b490eebc: BytesLike, + c_truebf28adcf( + c__bf28adcf: BytesLike, overrides?: CallOverrides ): Promise; }; diff --git a/typings/factories/AddressLib__factory.ts b/typings/factories/AddressLib__factory.ts index f4e52c91..689ff19d 100644 --- a/typings/factories/AddressLib__factory.ts +++ b/typings/factories/AddressLib__factory.ts @@ -10,11 +10,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__3858ce6a", + name: "c__6f8dca69", type: "bytes8", }, ], - name: "c_3858ce6a", + name: "c_6f8dca69", outputs: [], stateMutability: "pure", type: "function", @@ -23,11 +23,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__3858ce6a", + name: "c__6f8dca69", type: "bytes8", }, ], - name: "c_false3858ce6a", + name: "c_false6f8dca69", outputs: [ { internalType: "bool", @@ -42,11 +42,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__3858ce6a", + name: "c__6f8dca69", type: "bytes8", }, ], - name: "c_true3858ce6a", + name: "c_true6f8dca69", outputs: [ { internalType: "bool", @@ -60,7 +60,7 @@ const _abi = [ ]; const _bytecode = - "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80637e648d3014610050578063b60eb5fa146100af578063c8432912146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015e565b005b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610161565b60405180821515815260200191505060405180910390f35b6000919050565b50565b60006001905091905056fea164736f6c634300060c000a"; + "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80635b38394414610050578063b6dea462146100af578063ef24ac591461010e575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610162565b60405180821515815260200191505060405180910390f35b6101556004803603602081101561012457600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610169565b005b600060019050919050565b6000919050565b5056fea164736f6c634300060c000a"; type AddressLibConstructorParams = | [signer?: Signer] diff --git a/typings/factories/BlockLib__factory.ts b/typings/factories/BlockLib__factory.ts index 81000eaa..119b1df1 100644 --- a/typings/factories/BlockLib__factory.ts +++ b/typings/factories/BlockLib__factory.ts @@ -10,11 +10,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__69b78653", + name: "c__e404c745", type: "bytes8", }, ], - name: "c_69b78653", + name: "c_e404c745", outputs: [], stateMutability: "pure", type: "function", @@ -23,11 +23,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__69b78653", + name: "c__e404c745", type: "bytes8", }, ], - name: "c_false69b78653", + name: "c_falsee404c745", outputs: [ { internalType: "bool", @@ -42,11 +42,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__69b78653", + name: "c__e404c745", type: "bytes8", }, ], - name: "c_true69b78653", + name: "c_truee404c745", outputs: [ { internalType: "bool", @@ -60,7 +60,7 @@ const _abi = [ ]; const _bytecode = - "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c806391e6a20314610050578063a7a41f0f146100af578063c70d6afe1461010e575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610162565b60405180821515815260200191505060405180910390f35b6101556004803603602081101561012457600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610169565b005b600060019050919050565b6000919050565b5056fea164736f6c634300060c000a"; + "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c806352ac7248146100505780638e32a328146100af578063de14b68e146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015e565b005b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610161565b60405180821515815260200191505060405180910390f35b6000919050565b50565b60006001905091905056fea164736f6c634300060c000a"; type BlockLibConstructorParams = | [signer?: Signer] diff --git a/typings/factories/BytesLib__factory.ts b/typings/factories/BytesLib__factory.ts index 5cb3a8fa..86e41948 100644 --- a/typings/factories/BytesLib__factory.ts +++ b/typings/factories/BytesLib__factory.ts @@ -10,11 +10,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__374166e6", + name: "c__72a5b528", type: "bytes8", }, ], - name: "c_374166e6", + name: "c_72a5b528", outputs: [], stateMutability: "pure", type: "function", @@ -23,11 +23,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__374166e6", + name: "c__72a5b528", type: "bytes8", }, ], - name: "c_false374166e6", + name: "c_false72a5b528", outputs: [ { internalType: "bool", @@ -42,11 +42,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__374166e6", + name: "c__72a5b528", type: "bytes8", }, ], - name: "c_true374166e6", + name: "c_true72a5b528", outputs: [ { internalType: "bool", @@ -60,7 +60,7 @@ const _abi = [ ]; const _bytecode = - "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632a5f571d1461005057806371771952146100af578063c8fb9dc1146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015e565b005b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610161565b60405180821515815260200191505060405180910390f35b6000919050565b50565b60006001905091905056fea164736f6c634300060c000a"; + "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80635a97e344146100505780639c7ffe7d14610099578063a7c960f4146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b005b6100e0600480360360208110156100af57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015a565b60405180821515815260200191505060405180910390f35b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610165565b60405180821515815260200191505060405180910390f35b50565b600060019050919050565b600091905056fea164736f6c634300060c000a"; type BytesLibConstructorParams = | [signer?: Signer] diff --git a/typings/factories/ECDSAExtendedLib__factory.ts b/typings/factories/ECDSAExtendedLib__factory.ts index 6a92c46d..97bca9e8 100644 --- a/typings/factories/ECDSAExtendedLib__factory.ts +++ b/typings/factories/ECDSAExtendedLib__factory.ts @@ -13,11 +13,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__02b1372d", + name: "c__81f5e90e", type: "bytes8", }, ], - name: "c_02b1372d", + name: "c_81f5e90e", outputs: [], stateMutability: "pure", type: "function", @@ -26,11 +26,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__02b1372d", + name: "c__81f5e90e", type: "bytes8", }, ], - name: "c_false02b1372d", + name: "c_false81f5e90e", outputs: [ { internalType: "bool", @@ -45,11 +45,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__02b1372d", + name: "c__81f5e90e", type: "bytes8", }, ], - name: "c_true02b1372d", + name: "c_true81f5e90e", outputs: [ { internalType: "bool", @@ -63,7 +63,7 @@ const _abi = [ ]; const _bytecode = - "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80637a91f84e146100505780639e17a67c14610099578063f2db2a06146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b005b6100e0600480360360208110156100af57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015a565b60405180821515815260200191505060405180910390f35b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610165565b60405180821515815260200191505060405180910390f35b50565b600060019050919050565b600091905056fea164736f6c634300060c000a"; + "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80635a207af81461005057806369f277fb146100af578063d05ee1701461010e575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015e565b60405180821515815260200191505060405180910390f35b6101556004803603602081101561012457600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610169565b005b6000919050565b600060019050919050565b5056fea164736f6c634300060c000a"; type ECDSAExtendedLibConstructorParams = | [signer?: Signer] diff --git a/typings/factories/ECDSALib__factory.ts b/typings/factories/ECDSALib__factory.ts index aedbbd69..d57f2601 100644 --- a/typings/factories/ECDSALib__factory.ts +++ b/typings/factories/ECDSALib__factory.ts @@ -10,11 +10,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__b0cf6ac1", + name: "c__34283de1", type: "bytes8", }, ], - name: "c_b0cf6ac1", + name: "c_34283de1", outputs: [], stateMutability: "pure", type: "function", @@ -23,11 +23,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__b0cf6ac1", + name: "c__34283de1", type: "bytes8", }, ], - name: "c_falseb0cf6ac1", + name: "c_false34283de1", outputs: [ { internalType: "bool", @@ -42,11 +42,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__b0cf6ac1", + name: "c__34283de1", type: "bytes8", }, ], - name: "c_trueb0cf6ac1", + name: "c_true34283de1", outputs: [ { internalType: "bool", @@ -60,7 +60,7 @@ const _abi = [ ]; const _bytecode = - "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80631ad367e914610050578063292a6547146100af578063e27e7f071461010e575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015e565b60405180821515815260200191505060405180910390f35b6101556004803603602081101561012457600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610169565b005b6000919050565b600060019050919050565b5056fea164736f6c634300060c000a"; + "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c806394db32c614610050578063cbdfd97c14610099578063fa2752d7146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b005b6100e0600480360360208110156100af57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015a565b60405180821515815260200191505060405180910390f35b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610165565b60405180821515815260200191505060405180910390f35b50565b600060019050919050565b600091905056fea164736f6c634300060c000a"; type ECDSALibConstructorParams = | [signer?: Signer] diff --git a/typings/factories/ENSAbstractResolver__factory.ts b/typings/factories/ENSAbstractResolver__factory.ts index 1436ff15..ecb42615 100644 --- a/typings/factories/ENSAbstractResolver__factory.ts +++ b/typings/factories/ENSAbstractResolver__factory.ts @@ -14,11 +14,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__ac93193e", + name: "c__96741811", type: "bytes8", }, ], - name: "c_ac93193e", + name: "c_96741811", outputs: [], stateMutability: "pure", type: "function", @@ -27,11 +27,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__ac93193e", + name: "c__96741811", type: "bytes8", }, ], - name: "c_falseac93193e", + name: "c_false96741811", outputs: [ { internalType: "bool", @@ -46,11 +46,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__ac93193e", + name: "c__96741811", type: "bytes8", }, ], - name: "c_trueac93193e", + name: "c_true96741811", outputs: [ { internalType: "bool", diff --git a/typings/factories/GatewayV2__factory.ts b/typings/factories/GatewayV2__factory.ts new file mode 100644 index 00000000..34b74fac --- /dev/null +++ b/typings/factories/GatewayV2__factory.ts @@ -0,0 +1,634 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { Signer, utils, Contract, ContractFactory, Overrides } from "ethers"; +import { Provider, TransactionRequest } from "@ethersproject/providers"; +import type { GatewayV2, GatewayV2Interface } from "../GatewayV2"; + +const _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", + }, +]; + +const _bytecode = + "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000469050806001819055505061315e8061006d6000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806387d31313116100b8578063b5021b161161007c578063b5021b1614610349578063d0f710d614610365578063d2c83b9a14610395578063d305d0db146103b3578063d9f13021146103cf578063f92c5f7c146103eb57610142565b806387d31313146102b95780639a8a0592146102d75780639f255626146102f5578063a526d83b14610311578063ac2a08cd1461032d57610142565b8063538901341161010a57806353890134146101e95780635afaa7bb14610205578063714041561461022157806373e5a13f1461023d57806376db2b4c1461026d578063867519c61461029d57610142565b80630c68ba2114610147578063231badaf14610177578063371aa71a14610193578063392e53cd146101af578063485cc955146101cd575b600080fd5b610161600480360381019061015c9190611e5b565b61041b565b60405161016e9190612b23565b60405180910390f35b610191600480360381019061018c9190611f03565b610471565b005b6101ad60048036038101906101a89190611f03565b61056c565b005b6101b761060c565b6040516101c49190612b23565b60405180910390f35b6101e760048036038101906101e29190612103565b610662565b005b61020360048036038101906101fe9190611fc2565b6107fa565b005b61021f600480360381019061021a919061202e565b610894565b005b61023b60048036038101906102369190611e5b565b610a6c565b005b61025760048036038101906102529190612180565b610c87565b6040516102649190612b3e565b60405180910390f35b6102876004803603810190610282919061213f565b610cac565b6040516102949190612b3e565b60405180910390f35b6102b760048036038101906102b29190611e84565b610cd6565b005b6102c1610ce7565b6040516102ce9190612bb9565b60405180910390f35b6102df610d0d565b6040516102ec9190612df4565b60405180910390f35b61030f600480360381019061030a9190611fc2565b610d13565b005b61032b60048036038101906103269190611e5b565b610d23565b005b61034760048036038101906103429190611f03565b610dbb565b005b610363600480360381019061035e9190611f03565b610e5b565b005b61037f600480360381019061037a91906120ab565b610f57565b60405161038c9190612b23565b60405180910390f35b61039d610fb0565b6040516103aa9190612b9e565b60405180910390f35b6103cd60048036038101906103c89190611e84565b610fd6565b005b6103e960048036038101906103e4919061202e565b611072565b005b61040560048036038101906104009190611e5b565b61110c565b6040516104129190612df4565b60405180910390f35b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205484116104f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104e990612c54565b60405180910390fd5b60006105128261050488888888611168565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061056486828686611286565b505050505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166105f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ef90612cf4565b60405180910390fd5b6106058585858585610e5b565b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146106f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e790612c14565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060606107be816116f1565b507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516107ee9190612a78565b60405180910390a15050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087d90612cf4565b60405180910390fd5b6108908282610d13565b5050565b60008251116108d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cf90612c94565b60405180910390fd5b600080600090505b8351811015610a265760003073ffffffffffffffffffffffffffffffffffffffff1685838151811061090e57fe5b60200260200101516040516109239190612994565b6000604051808303816000865af19150503d8060008114610960576040519150601f19603f3d011682016040523d82523d6000602084013e610965565b606091505b5050905083156109b457806109af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a690612c34565b60405180910390fd5b6109ca565b8080156109bf575082155b156109c957600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106109f857fe5b602002602001015183604051610a1093929190612abc565b60405180910390a15080806001019150506108e0565b5080610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612dd4565b60405180910390fd5b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90612cf4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5e90612db4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bf3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bea90612d14565b60405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c7c929190612a93565b60405180910390a150565b6000610ca58260000151836020015184604001518560600151611168565b9050919050565b6000610ccf82600001518360200151846040015185606001518660800151611749565b9050919050565b610ce283338484611286565b505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b610d1f33338484611286565b5050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612cf4565b60405180910390fd5b610db8816117af565b50565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610e47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3e90612cf4565b60405180910390fd5b610e548585858585610471565b5050505050565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed390612c54565b60405180910390fd5b6000610efd82610eef888888883a611749565b6111cb90919063ffffffff16565b905084600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f86828686611286565b505050505050565b6000610fa78484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611940565b90509392505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105990612cf4565b60405180910390fd5b61106d838383610cd6565b505050565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f590612cf4565b60405180910390fd5b6111088282610894565b5050565b60006111616001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119ae90919063ffffffff16565b9050919050565b60006111c17f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661119a87611a03565b6040516020016111ad94939291906128f7565b604051602081830303815290604052611a66565b9050949350505050565b6000806000905060418351141561127c5760008060006020860151925060408601519150606086015160001a9050601b8160ff16101561120c57601b810190505b601b8160ff1614806112215750601c8160ff16145b1561127857600187828585604051600081526020016040526040516112499493929190612b59565b6020604051602081039080840390855afa15801561126b573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156112f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ed90612c74565b60405180910390fd5b600082511161133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612d94565b60405180910390fd5b815181511461137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137590612cd4565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461155257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b815260040161140e929190612afa565b60206040518083038186803b15801561142657600080fd5b505afa15801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190612082565b806115125750600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b81526004016114c1929190612afa565b60206040518083038186803b1580156114d957600080fd5b505afa1580156114ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115119190612082565b5b611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890612cb4565b60405180910390fd5b5b600080600090505b82518110156116e957600073ffffffffffffffffffffffffffffffffffffffff1684828151811061158757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156115e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dd90612bd4565b60405180910390fd5b8381815181106115f257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1683828151811061161c57fe5b60200260200101518787604051602001611638939291906129ab565b6040516020818303038152906040526040516116549190612994565b6000604051808303816000865af19150503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b505080925050816116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d390612d34565b60405180910390fd5b808060010191505061155a565b505050505050565b60008151141561170957611704326117af565b611746565b60008151905060005b818110156117435761173683828151811061172957fe5b60200260200101516117af565b8080600101915050611712565b50505b50565b60006117a47f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad87878761177b88611a03565b8760405160200161179095949392919061293d565b604051602081830303815290604052611a66565b905095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561181f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181690612bf4565b60405180910390fd5b600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156118ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a390612d74565b60405180910390fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051611935929190612a93565b60405180910390a150565b60008061195683856111cb90919063ffffffff16565b9050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000808284019050838110156119f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f090612d54565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015611a5b5782858281518110611a2457fe5b6020026020010151604051602001611a3d9291906129e4565b60405160208183030381529060405292508080600101915050611a0f565b508192505050919050565b6000611a9f600154308585604051602001611a849493929190612a2e565b60405160208183030381529060405280519060200120611aa7565b905092915050565b600081604051602001611aba9190612a08565b604051602081830303815290604052805190602001209050919050565b600081359050611ae6816130c7565b92915050565b600082601f830112611afd57600080fd5b8135611b10611b0b82612e3c565b612e0f565b91508181835260208401935060208101905083856020840282011115611b3557600080fd5b60005b83811015611b655781611b4b8882611ad7565b845260208401935060208301925050600181019050611b38565b5050505092915050565b600082601f830112611b8057600080fd5b8135611b93611b8e82612e64565b612e0f565b9150818183526020840193506020810190508360005b83811015611bd95781358601611bbf8882611c6c565b845260208401935060208301925050600181019050611ba9565b5050505092915050565b600081359050611bf2816130de565b92915050565b600081519050611c07816130de565b92915050565b600081359050611c1c816130f5565b92915050565b60008083601f840112611c3457600080fd5b8235905067ffffffffffffffff811115611c4d57600080fd5b602083019150836001820283011115611c6557600080fd5b9250929050565b600082601f830112611c7d57600080fd5b8135611c90611c8b82612e8c565b612e0f565b91508082526020830160208301858383011115611cac57600080fd5b611cb783828461302f565b50505092915050565b600081359050611ccf8161310c565b92915050565b600081359050611ce481613123565b92915050565b600060a08284031215611cfc57600080fd5b611d0660a0612e0f565b90506000611d1684828501611ad7565b6000830152506020611d2a84828501611e46565b602083015250604082013567ffffffffffffffff811115611d4a57600080fd5b611d5684828501611aec565b604083015250606082013567ffffffffffffffff811115611d7657600080fd5b611d8284828501611b6f565b6060830152506080611d9684828501611e46565b60808301525092915050565b600060808284031215611db457600080fd5b611dbe6080612e0f565b90506000611dce84828501611ad7565b6000830152506020611de284828501611e46565b602083015250604082013567ffffffffffffffff811115611e0257600080fd5b611e0e84828501611aec565b604083015250606082013567ffffffffffffffff811115611e2e57600080fd5b611e3a84828501611b6f565b60608301525092915050565b600081359050611e558161313a565b92915050565b600060208284031215611e6d57600080fd5b6000611e7b84828501611ad7565b91505092915050565b600080600060608486031215611e9957600080fd5b6000611ea786828701611ad7565b935050602084013567ffffffffffffffff811115611ec457600080fd5b611ed086828701611aec565b925050604084013567ffffffffffffffff811115611eed57600080fd5b611ef986828701611b6f565b9150509250925092565b600080600080600060a08688031215611f1b57600080fd5b6000611f2988828901611ad7565b9550506020611f3a88828901611e46565b945050604086013567ffffffffffffffff811115611f5757600080fd5b611f6388828901611aec565b935050606086013567ffffffffffffffff811115611f8057600080fd5b611f8c88828901611b6f565b925050608086013567ffffffffffffffff811115611fa957600080fd5b611fb588828901611c6c565b9150509295509295909350565b60008060408385031215611fd557600080fd5b600083013567ffffffffffffffff811115611fef57600080fd5b611ffb85828601611aec565b925050602083013567ffffffffffffffff81111561201857600080fd5b61202485828601611b6f565b9150509250929050565b6000806040838503121561204157600080fd5b600083013567ffffffffffffffff81111561205b57600080fd5b61206785828601611b6f565b925050602061207885828601611be3565b9150509250929050565b60006020828403121561209457600080fd5b60006120a284828501611bf8565b91505092915050565b6000806000604084860312156120c057600080fd5b60006120ce86828701611c0d565b935050602084013567ffffffffffffffff8111156120eb57600080fd5b6120f786828701611c22565b92509250509250925092565b6000806040838503121561211657600080fd5b600061212485828601611cc0565b925050602061213585828601611cd5565b9150509250929050565b60006020828403121561215157600080fd5b600082013567ffffffffffffffff81111561216b57600080fd5b61217784828501611cea565b91505092915050565b60006020828403121561219257600080fd5b600082013567ffffffffffffffff8111156121ac57600080fd5b6121b884828501611da2565b91505092915050565b60006121cd83836121f7565b60208301905092915050565b6121e281612fb1565b82525050565b6121f181612f2e565b82525050565b61220081612f2e565b82525050565b61221761221282612f2e565b613071565b82525050565b600061222882612ec8565b6122328185612eeb565b935061223d83612eb8565b8060005b8381101561226e57815161225588826121c1565b975061226083612ede565b925050600181019050612241565b5085935050505092915050565b61228481612f40565b82525050565b61229381612f4c565b82525050565b6122aa6122a582612f4c565b613083565b82525050565b60006122bb82612ed3565b6122c58185612ef6565b93506122d581856020860161303e565b6122de816130a9565b840191505092915050565b60006122f482612ed3565b6122fe8185612f07565b935061230e81856020860161303e565b80840191505092915050565b61232381612fc3565b82525050565b61233281612fe7565b82525050565b6000612345601b83612f12565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000612385601c83612f23565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006123c5602083612f12565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b6000612405602f83612f12565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061246b601783612f12565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006124ab603283612f12565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b6000612511602583612f12565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612577602683612f12565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006125dd602883612f12565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612643601683612f12565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000612683602683612f12565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006126e9601f83612f12565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000612729602383612f12565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061278f601e83612f12565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b60006127cf602083612f12565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b600061280f602083612f12565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b600061284f601b83612f12565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b600061288f601d83612f12565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b6128cb81612f9a565b82525050565b6128e26128dd82612f9a565b61309f565b82525050565b6128f181612fa4565b82525050565b60006129038287612206565b60148201915061291382866128d1565b602082019150612923828561221d565b915061292f82846122e9565b915081905095945050505050565b60006129498288612206565b60148201915061295982876128d1565b602082019150612969828661221d565b915061297582856122e9565b915061298182846128d1565b6020820191508190509695505050505050565b60006129a082846122e9565b915081905092915050565b60006129b782866122e9565b91506129c38285612206565b6014820191506129d38284612206565b601482019150819050949350505050565b60006129f082856122e9565b91506129fc82846122e9565b91508190509392505050565b6000612a1382612378565b9150612a1f8284612299565b60208201915081905092915050565b6000612a3a82876128d1565b602082019150612a4a8286612206565b601482019150612a5a8285612299565b602082019150612a6a82846122e9565b915081905095945050505050565b6000602082019050612a8d60008301846121d9565b92915050565b6000604082019050612aa860008301856121d9565b612ab560208301846121e8565b9392505050565b6000606082019050612ad160008301866121d9565b8181036020830152612ae381856122b0565b9050612af2604083018461227b565b949350505050565b6000604082019050612b0f60008301856121e8565b612b1c60208301846121e8565b9392505050565b6000602082019050612b38600083018461227b565b92915050565b6000602082019050612b53600083018461228a565b92915050565b6000608082019050612b6e600083018761228a565b612b7b60208301866128e8565b612b88604083018561228a565b612b95606083018461228a565b95945050505050565b6000602082019050612bb3600083018461231a565b92915050565b6000602082019050612bce6000830184612329565b92915050565b60006020820190508181036000830152612bed81612338565b9050919050565b60006020820190508181036000830152612c0d816123b8565b9050919050565b60006020820190508181036000830152612c2d816123f8565b9050919050565b60006020820190508181036000830152612c4d8161245e565b9050919050565b60006020820190508181036000830152612c6d8161249e565b9050919050565b60006020820190508181036000830152612c8d81612504565b9050919050565b60006020820190508181036000830152612cad8161256a565b9050919050565b60006020820190508181036000830152612ccd816125d0565b9050919050565b60006020820190508181036000830152612ced81612636565b9050919050565b60006020820190508181036000830152612d0d81612676565b9050919050565b60006020820190508181036000830152612d2d816126dc565b9050919050565b60006020820190508181036000830152612d4d8161271c565b9050919050565b60006020820190508181036000830152612d6d81612782565b9050919050565b60006020820190508181036000830152612d8d816127c2565b9050919050565b60006020820190508181036000830152612dad81612802565b9050919050565b60006020820190508181036000830152612dcd81612842565b9050919050565b60006020820190508181036000830152612ded81612882565b9050919050565b6000602082019050612e0960008301846128c2565b92915050565b6000604051905081810181811067ffffffffffffffff82111715612e3257600080fd5b8060405250919050565b600067ffffffffffffffff821115612e5357600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612e7b57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115612ea357600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000612f3982612f7a565b9050919050565b60008115159050919050565b6000819050919050565b6000612f6182612f2e565b9050919050565b6000612f7382612f2e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000612fbc8261300b565b9050919050565b6000612fce82612fd5565b9050919050565b6000612fe082612f7a565b9050919050565b6000612ff282612ff9565b9050919050565b600061300482612f7a565b9050919050565b60006130168261301d565b9050919050565b600061302882612f7a565b9050919050565b82818337600083830152505050565b60005b8381101561305c578082015181840152602081019050613041565b8381111561306b576000848401525b50505050565b600061307c8261308d565b9050919050565b6000819050919050565b6000613098826130ba565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b6130d081612f2e565b81146130db57600080fd5b50565b6130e781612f40565b81146130f257600080fd5b50565b6130fe81612f4c565b811461310957600080fd5b50565b61311581612f56565b811461312057600080fd5b50565b61312c81612f68565b811461313757600080fd5b50565b61314381612f9a565b811461314e57600080fd5b5056fea164736f6c634300060c000a"; + +type GatewayV2ConstructorParams = + | [signer?: Signer] + | ConstructorParameters; + +const isSuperArgs = ( + xs: GatewayV2ConstructorParams +): xs is ConstructorParameters => xs.length > 1; + +export class GatewayV2__factory extends ContractFactory { + constructor(...args: GatewayV2ConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + } + + deploy( + overrides?: Overrides & { from?: string | Promise } + ): Promise { + return super.deploy(overrides || {}) as Promise; + } + getDeployTransaction( + overrides?: Overrides & { from?: string | Promise } + ): TransactionRequest { + return super.getDeployTransaction(overrides || {}); + } + attach(address: string): GatewayV2 { + return super.attach(address) as GatewayV2; + } + connect(signer: Signer): GatewayV2__factory { + return super.connect(signer) as GatewayV2__factory; + } + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): GatewayV2Interface { + return new utils.Interface(_abi) as GatewayV2Interface; + } + static connect( + address: string, + signerOrProvider: Signer | Provider + ): GatewayV2 { + return new Contract(address, _abi, signerOrProvider) as GatewayV2; + } +} diff --git a/typings/factories/LibAsset__factory.ts b/typings/factories/LibAsset__factory.ts index 855a1790..159d0515 100644 --- a/typings/factories/LibAsset__factory.ts +++ b/typings/factories/LibAsset__factory.ts @@ -10,11 +10,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__61c7bb39", + name: "c__ba3e7152", type: "bytes8", }, ], - name: "c_61c7bb39", + name: "c_ba3e7152", outputs: [], stateMutability: "pure", type: "function", @@ -23,11 +23,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__61c7bb39", + name: "c__ba3e7152", type: "bytes8", }, ], - name: "c_false61c7bb39", + name: "c_falseba3e7152", outputs: [ { internalType: "bool", @@ -42,11 +42,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__61c7bb39", + name: "c__ba3e7152", type: "bytes8", }, ], - name: "c_true61c7bb39", + name: "c_trueba3e7152", outputs: [ { internalType: "bool", @@ -60,7 +60,7 @@ const _abi = [ ]; const _bytecode = - "0x6101a5610053600b82828239805160001a607314610046577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632f016f6f146100505780636a550ef71461006c578063bb9e0f711461009c575b600080fd5b61006a600480360381019061006591906100f6565b6100cc565b005b610086600480360381019061008191906100f6565b6100cf565b604051610093919061012e565b60405180910390f35b6100b660048036038101906100b191906100f6565b6100da565b6040516100c3919061012e565b60405180910390f35b50565b600060019050919050565b6000919050565b6000813590506100f081610181565b92915050565b60006020828403121561010857600080fd5b6000610116848285016100e1565b91505092915050565b61012881610149565b82525050565b6000602082019050610143600083018461011f565b92915050565b60008115159050919050565b60007fffffffffffffffff00000000000000000000000000000000000000000000000082169050919050565b61018a81610155565b811461019557600080fd5b5056fea164736f6c6343000804000a"; + "0x6101a5610053600b82828239805160001a607314610046577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80636c0beb5c146100505780637f37df3614610080578063fcee93be146100b0575b600080fd5b61006a600480360381019061006591906100f6565b6100cc565b604051610077919061012e565b60405180910390f35b61009a600480360381019061009591906100f6565b6100d7565b6040516100a7919061012e565b60405180910390f35b6100ca60048036038101906100c591906100f6565b6100de565b005b600060019050919050565b6000919050565b50565b6000813590506100f081610181565b92915050565b60006020828403121561010857600080fd5b6000610116848285016100e1565b91505092915050565b61012881610149565b82525050565b6000602082019050610143600083018461011f565b92915050565b60008115159050919050565b60007fffffffffffffffff00000000000000000000000000000000000000000000000082169050919050565b61018a81610155565b811461019557600080fd5b5056fea164736f6c6343000804000a"; type LibAssetConstructorParams = | [signer?: Signer] diff --git a/typings/factories/SafeMathLib__factory.ts b/typings/factories/SafeMathLib__factory.ts index 0d118c14..356cf04f 100644 --- a/typings/factories/SafeMathLib__factory.ts +++ b/typings/factories/SafeMathLib__factory.ts @@ -10,11 +10,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__60aa1e30", + name: "c__7fef3447", type: "bytes8", }, ], - name: "c_60aa1e30", + name: "c_7fef3447", outputs: [], stateMutability: "pure", type: "function", @@ -23,11 +23,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__60aa1e30", + name: "c__7fef3447", type: "bytes8", }, ], - name: "c_false60aa1e30", + name: "c_false7fef3447", outputs: [ { internalType: "bool", @@ -42,11 +42,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__60aa1e30", + name: "c__7fef3447", type: "bytes8", }, ], - name: "c_true60aa1e30", + name: "c_true7fef3447", outputs: [ { internalType: "bool", @@ -60,7 +60,7 @@ const _abi = [ ]; const _bytecode = - "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80631c8d1f43146100505780638b0042a514610099578063e7b2afe7146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b005b6100e0600480360360208110156100af57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015a565b60405180821515815260200191505060405180910390f35b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610165565b60405180821515815260200191505060405180910390f35b50565b600060019050919050565b600091905056fea164736f6c634300060c000a"; + "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80630bf70d0014610050578063a9f1debc146100af578063d60334891461010e575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015e565b60405180821515815260200191505060405180910390f35b6101556004803603602081101561012457600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610169565b005b6000919050565b600060019050919050565b5056fea164736f6c634300060c000a"; type SafeMathLibConstructorParams = | [signer?: Signer] diff --git a/typings/factories/StringsLib__factory.ts b/typings/factories/StringsLib__factory.ts index a30ebcaf..66ae906c 100644 --- a/typings/factories/StringsLib__factory.ts +++ b/typings/factories/StringsLib__factory.ts @@ -10,11 +10,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__b490eebc", + name: "c__bf28adcf", type: "bytes8", }, ], - name: "c_b490eebc", + name: "c_bf28adcf", outputs: [], stateMutability: "pure", type: "function", @@ -23,11 +23,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__b490eebc", + name: "c__bf28adcf", type: "bytes8", }, ], - name: "c_falseb490eebc", + name: "c_falsebf28adcf", outputs: [ { internalType: "bool", @@ -42,11 +42,11 @@ const _abi = [ inputs: [ { internalType: "bytes8", - name: "c__b490eebc", + name: "c__bf28adcf", type: "bytes8", }, ], - name: "c_trueb490eebc", + name: "c_truebf28adcf", outputs: [ { internalType: "bool", @@ -60,7 +60,7 @@ const _abi = [ ]; const _bytecode = - "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c806393247ceb1461005057806398f0f7b514610099578063b99e549f146100f8575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b005b6100e0600480360360208110156100af57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061015a565b60405180821515815260200191505060405180910390f35b61013f6004803603602081101561010e57600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610161565b60405180821515815260200191505060405180910390f35b50565b6000919050565b60006001905091905056fea164736f6c634300060c000a"; + "0x610179610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c8063aa72bfee14610050578063b958fcd0146100af578063de2f5a761461010e575b600080fd5b6100976004803603602081101561006657600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610157565b60405180821515815260200191505060405180910390f35b6100f6600480360360208110156100c557600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610162565b60405180821515815260200191505060405180910390f35b6101556004803603602081101561012457600080fd5b81019080803577ffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610169565b005b600060019050919050565b6000919050565b5056fea164736f6c634300060c000a"; type StringsLibConstructorParams = | [signer?: Signer] diff --git a/typings/index.ts b/typings/index.ts index 3b003d0a..a84460dd 100644 --- a/typings/index.ts +++ b/typings/index.ts @@ -86,6 +86,7 @@ export type { ENSTextResolver } from "./ENSTextResolver"; export type { ExternalAccountRegistry } from "./ExternalAccountRegistry"; export type { Gateway } from "./Gateway"; export type { GatewayRecipient } from "./GatewayRecipient"; +export type { GatewayV2 } from "./GatewayV2"; export type { GatewayRecipientMock } from "./GatewayRecipientMock"; export type { PaymentDepositAccount } from "./PaymentDepositAccount"; export type { PaymentRegistry } from "./PaymentRegistry"; @@ -178,6 +179,7 @@ export { ENSTextResolver__factory } from "./factories/ENSTextResolver__factory"; export { ExternalAccountRegistry__factory } from "./factories/ExternalAccountRegistry__factory"; export { Gateway__factory } from "./factories/Gateway__factory"; export { GatewayRecipient__factory } from "./factories/GatewayRecipient__factory"; +export { GatewayV2__factory } from "./factories/GatewayV2__factory"; export { GatewayRecipientMock__factory } from "./factories/GatewayRecipientMock__factory"; export { PaymentDepositAccount__factory } from "./factories/PaymentDepositAccount__factory"; export { PaymentRegistry__factory } from "./factories/PaymentRegistry__factory";