From e94619a95f7fb4d76fe4db3196b21afccc6d04ab Mon Sep 17 00:00:00 2001 From: Luke Wickens Date: Mon, 28 Nov 2022 12:01:18 +0000 Subject: [PATCH] Redeployed contracts to neonDevnet --- DEPLOYMENTS.md | 25 +- deployments/neonDevnet/BalancesHelper.json | 10 +- deployments/neonDevnet/BalancesHelperV2.json | 10 +- deployments/neonDevnet/ENSController.json | 10 +- deployments/neonDevnet/ENSHelper.json | 10 +- deployments/neonDevnet/ENSRegistry.json | 14 +- .../neonDevnet/ENSReverseRegistrar.json | 10 +- .../neonDevnet/ExternalAccountRegistry.json | 10 +- deployments/neonDevnet/Gateway.json | 16 +- deployments/neonDevnet/GatewayV2.json | 926 ++++++++++++++++++ deployments/neonDevnet/PaymentRegistry.json | 48 +- .../PersonalAccountImplementationV1.json | 12 +- .../neonDevnet/PersonalAccountRegistry.json | 26 +- deployments/neonDevnet/WrappedWeiToken.json | 12 +- .../6ff48c01406545b171c1098ac74d4555.json | 97 ++ .../c6bcc786074bb5f47af1ba8ec29021b3.json | 157 +++ 16 files changed, 1287 insertions(+), 106 deletions(-) create mode 100644 deployments/neonDevnet/GatewayV2.json create mode 100644 deployments/neonDevnet/solcInputs/6ff48c01406545b171c1098ac74d4555.json create mode 100644 deployments/neonDevnet/solcInputs/c6bcc786074bb5f47af1ba8ec29021b3.json diff --git a/DEPLOYMENTS.md b/DEPLOYMENTS.md index 6d315935..3db8a24a 100644 --- a/DEPLOYMENTS.md +++ b/DEPLOYMENTS.md @@ -30,7 +30,7 @@ | `BalancesHelper` | `celo` | 0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b | 0xfc0dc010dd2df5473efc9e99d884818145c485de11993612ee8873680eed7b76 | | `BalancesHelper` | `celoTest` | 0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b | 0x6b910a25366bfda341b56258532d882579db1de46ace8e7457cc8da90cf9877b | | `BalancesHelper` | `optimismGoerli` | [0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b](https://goerli-optimism.etherscan.io/address/0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b) | [0x33f5ec14bb8f3e5c17a8e5dc540cfb5d11fc7dd001248af201f543ed35806aa0](https://goerli-optimism.etherscan.io/tx/0x33f5ec14bb8f3e5c17a8e5dc540cfb5d11fc7dd001248af201f543ed35806aa0) | -| `BalancesHelper` | `neonDevnet` | 0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b | 0x154f16bb095d820f6e20d631b2e7df8d0e3f1a82732e4ea463b5584cbb37ecd9 | +| `BalancesHelper` | `neonDevnet` | [0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b](https://neonscan.org/address/0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b) | [0x1ace0e0cbe0344d55bbfbc5a94a7e1a9a309f2442c8b4146af639af99249c84e](https://neonscan.org/tx/0x1ace0e0cbe0344d55bbfbc5a94a7e1a9a309f2442c8b4146af639af99249c84e) | | `BalancesHelper` | `arbitrumNova` | 0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b | 0xf4ffff6eccf68e8df568688c91c45cf82f2f7fba3401f92be057207fa3e3cff8 | | `BalancesHelper` | `arbitrumNitro` | 0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b | 0x34943a88565f9173b84843e04c737c6555210dae946eaa7d9e0ed72e9fc72171 | | `BalancesHelper` | `etherspot` | 0xa6C165E3539A2bE6d55e2935EC9979D8C850A21b | 0xac7270105c381ce52e137b815727c88f9f03a0005afa776154de199de41c1d33 | @@ -55,7 +55,7 @@ | `BalancesHelperV2` | `fuseSparknet` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0x794c538975130b41812df708b2174c971ab7af6fa1e19bb5d2b4301c7071c893 | | `BalancesHelperV2` | `celo` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0xfdc0e0d89733dfb237e8b3f4fa36810b84d079d6ecf0b50e435e9542d8b8cdbc | | `BalancesHelperV2` | `optimismGoerli` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://goerli-optimism.etherscan.io/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0xde45800a299518c29d682ddc7038e622bcf417ce0db5404fbd0d4bf4c606f3aa](https://goerli-optimism.etherscan.io/tx/0xde45800a299518c29d682ddc7038e622bcf417ce0db5404fbd0d4bf4c606f3aa) | -| `BalancesHelperV2` | `neonDevnet` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0xf1b8cb6bbef86256c57e6ea7b672377a8ea4033e556da2b781203cc4e7bf97d5 | +| `BalancesHelperV2` | `neonDevnet` | [0xe5A160F89f330cc933816E896a3F36376DE0a835](https://neonscan.org/address/0xe5A160F89f330cc933816E896a3F36376DE0a835) | [0xb3723d3c80a4ba1370984041779b7dab86056a8624c31b11970ba2dbc959f96f](https://neonscan.org/tx/0xb3723d3c80a4ba1370984041779b7dab86056a8624c31b11970ba2dbc959f96f) | | `BalancesHelperV2` | `arbitrumNova` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0xf27547e4bd44530c8008614dcca0af25eaedeec002634d81dd0bea6a1442f96c | | `BalancesHelperV2` | `arbitrumNitro` | 0xe5A160F89f330cc933816E896a3F36376DE0a835 | 0x887cc509e64c1d4812491134cac0ebd165abcfa377807f2437404f2d9d303749 | | `CBridgeFacet` | `goerli` | [0x9d70f5253949Eb67850C3f1e7371f15b955ee073](https://goerli.etherscan.io/address/0x9d70f5253949Eb67850C3f1e7371f15b955ee073) | [0x047d8e991a3dc6bac32e2ef5d08078ecbf10abe3f32c20a7d87b32a2647a2390](https://goerli.etherscan.io/tx/0x047d8e991a3dc6bac32e2ef5d08078ecbf10abe3f32c20a7d87b32a2647a2390) | @@ -122,7 +122,7 @@ | `ENSController` | `celo` | 0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08 | 0x506af71c933202ab4deb3de6599c0c5ec5f07af0750837ffa38216fddd1af7eb | | `ENSController` | `celoTest` | 0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08 | 0xc45d57662670d6ab754683f4a030859fa8d1b0fad29a6dd335b768f259665ecd | | `ENSController` | `optimismGoerli` | [0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08](https://goerli-optimism.etherscan.io/address/0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08) | [0x2e5f824e8475d590e325219a650799c5768de3b8a21035577b2e608b802036ca](https://goerli-optimism.etherscan.io/tx/0x2e5f824e8475d590e325219a650799c5768de3b8a21035577b2e608b802036ca) | -| `ENSController` | `neonDevnet` | 0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08 | 0x24da3b71a66b5ecbc9ae73762d856309525b4e69d7735977b2e29f9f443c7869 | +| `ENSController` | `neonDevnet` | [0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08](https://neonscan.org/address/0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08) | [0x3e4a01a335da80d736867d8b00c38fe99d39affa6eb741f61cfe4307ce33a2f6](https://neonscan.org/tx/0x3e4a01a335da80d736867d8b00c38fe99d39affa6eb741f61cfe4307ce33a2f6) | | `ENSController` | `arbitrumNova` | 0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08 | 0x9eb6213b2320243c84290cac3acf4619a5ffffa586505c44a92f3bc4b6b7a4f9 | | `ENSController` | `arbitrumNitro` | 0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08 | 0x1ffee3063052940312d55fb7c90cc30212049c49f3e4ad3f1bef334484e98472 | | `ENSController` | `etherspot` | 0xE23c8f8aB1Cdd56D89F181c22Bf43e5b53871E08 | 0x2dd4c61274c93e97aa5ce56138d7d67d4cc74503a97b0e2af4f2dee9844c7253 | @@ -154,7 +154,7 @@ | `ENSHelper` | `celo` | 0xF330b17e19474762E6F408D7dCf0327264d4A2C0 | 0x396ec3c9f1f3a8625402798581ae2cb925d2ae1d6743ad9e7b498e814c570057 | | `ENSHelper` | `celoTest` | 0xF330b17e19474762E6F408D7dCf0327264d4A2C0 | 0x42c9dce6afca7bd38dee552c2b8724061e01bf9a47ecff91f3094e730bd80caf | | `ENSHelper` | `optimismGoerli` | [0xF330b17e19474762E6F408D7dCf0327264d4A2C0](https://goerli-optimism.etherscan.io/address/0xF330b17e19474762E6F408D7dCf0327264d4A2C0) | [0x71d601c937ca72c2bba74fccfeb0757465d9ac382360c94a6480b563f09dde76](https://goerli-optimism.etherscan.io/tx/0x71d601c937ca72c2bba74fccfeb0757465d9ac382360c94a6480b563f09dde76) | -| `ENSHelper` | `neonDevnet` | 0xF330b17e19474762E6F408D7dCf0327264d4A2C0 | 0x537758f8c59f5f98525af01cac5f20a29ccab5bdf76a04e327222c9c94c099bb | +| `ENSHelper` | `neonDevnet` | [0xF330b17e19474762E6F408D7dCf0327264d4A2C0](https://neonscan.org/address/0xF330b17e19474762E6F408D7dCf0327264d4A2C0) | [0x9ccb74f863097ed19ced9d6999366ee01a5bcc8215ff5fade4e670db0c72f823](https://neonscan.org/tx/0x9ccb74f863097ed19ced9d6999366ee01a5bcc8215ff5fade4e670db0c72f823) | | `ENSHelper` | `arbitrumNova` | 0xF330b17e19474762E6F408D7dCf0327264d4A2C0 | 0xe129a9c3c8a826a0b90b348bfb7f0dab93f7833faf4fafc6a1f650af78ff7b9e | | `ENSHelper` | `arbitrumNitro` | 0xF330b17e19474762E6F408D7dCf0327264d4A2C0 | 0x020b653764ca2fc7e9cd091d68878fed403ae42dcc22dcf66d9f594d8be78a01 | | `ENSHelper` | `etherspot` | 0xF330b17e19474762E6F408D7dCf0327264d4A2C0 | 0x7cf8135b5b04916485a8ec064d304c46cfe871e613ea14e128c51b6616f0d0f0 | @@ -185,7 +185,7 @@ | `ENSRegistry` | `celo` | 0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688 | 0xfbd52c01cc283b000acfe5679ec13cd4956991d14ef2d9d899cc9cc4a30566aa | | `ENSRegistry` | `celoTest` | 0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688 | 0x6361fb53ae0e03f60f5886aa101620f050d2ca0a94765e45dd0be8fabe3e1f5a | | `ENSRegistry` | `optimismGoerli` | [0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688](https://goerli-optimism.etherscan.io/address/0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688) | [0x696e8a45759e4155f43849d794ea3c81a3c3c5024d072eb9e12fd6d1ba0e448a](https://goerli-optimism.etherscan.io/tx/0x696e8a45759e4155f43849d794ea3c81a3c3c5024d072eb9e12fd6d1ba0e448a) | -| `ENSRegistry` | `neonDevnet` | 0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688 | 0x8e856f881e3a281aa213b7e0dfc652b333e7c7c54a7e6cec6a1d90fd1f7733c3 | +| `ENSRegistry` | `neonDevnet` | [0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688](https://neonscan.org/address/0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688) | [0xfb872a42a5c849acdaa0ca6f108abb6d5c846523885db2d8dfd447ccc3bf06b6](https://neonscan.org/tx/0xfb872a42a5c849acdaa0ca6f108abb6d5c846523885db2d8dfd447ccc3bf06b6) | | `ENSRegistry` | `arbitrumNova` | 0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688 | 0xe8c1efe9378204075510cebe52c49b883f718b5a2ebd2a7e7804a348e0c899ea | | `ENSRegistry` | `arbitrumNitro` | 0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688 | 0xa736c7bd9a26ba6a4d32962ac3dbef7110cf87e6aecce2226a993e4f2a0f088f | | `ENSRegistry` | `etherspot` | 0xf17BCfd10B65fD0792dEef7a17Aa08B4b0086688 | 0x1b419734e3beb7a4d97e835e3b0f594ddb74290ab7fc940ba3c5a3b37e035775 | @@ -216,7 +216,7 @@ | `ENSReverseRegistrar` | `celo` | 0x523C92966e9d2067ba547f59D51E907c20FD8761 | 0x3fda2be4237a4ca2103d46d8755edb14c5ea4bef154eabfc4aa91280d9f16836 | | `ENSReverseRegistrar` | `celoTest` | 0x523C92966e9d2067ba547f59D51E907c20FD8761 | 0x178149172d88aa3d6b00fde5ba0d0bc120924349c5fb5030f43136d86cbb7383 | | `ENSReverseRegistrar` | `optimismGoerli` | [0x523C92966e9d2067ba547f59D51E907c20FD8761](https://goerli-optimism.etherscan.io/address/0x523C92966e9d2067ba547f59D51E907c20FD8761) | [0x63359a907d3dadd5bf136ab968d6515a5d6148ccac30bf8ac57c5cd88d84a7d8](https://goerli-optimism.etherscan.io/tx/0x63359a907d3dadd5bf136ab968d6515a5d6148ccac30bf8ac57c5cd88d84a7d8) | -| `ENSReverseRegistrar` | `neonDevnet` | 0x523C92966e9d2067ba547f59D51E907c20FD8761 | 0x7c0f450722b503fc6a836fdb009f5f7d30c53ebc31599b58e83082b12ee9276b | +| `ENSReverseRegistrar` | `neonDevnet` | [0x523C92966e9d2067ba547f59D51E907c20FD8761](https://neonscan.org/address/0x523C92966e9d2067ba547f59D51E907c20FD8761) | [0x57ae6885e36a19ffd46ad47b4ba57503499abc0c1de0836ee2a381b757d1f1ab](https://neonscan.org/tx/0x57ae6885e36a19ffd46ad47b4ba57503499abc0c1de0836ee2a381b757d1f1ab) | | `ENSReverseRegistrar` | `arbitrumNova` | 0x523C92966e9d2067ba547f59D51E907c20FD8761 | 0xffa80fe1696aa362243347324934110b02fec48ddd62d7cf1c97a74291e2bb2b | | `ENSReverseRegistrar` | `arbitrumNitro` | 0x523C92966e9d2067ba547f59D51E907c20FD8761 | 0x70de389b15700bc9fde25e81f4d6c53549d74665209a237ca24e054bb0111d49 | | `ENSReverseRegistrar` | `etherspot` | 0x523C92966e9d2067ba547f59D51E907c20FD8761 | 0x3193533de6611dc509866e81e0d955674b8d351a82ca5db095e00b6e40414869 | @@ -248,7 +248,7 @@ | `ExternalAccountRegistry` | `celo` | 0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc | 0x01dbf81a93f634c4352e223da76269ade120e638386bfdb5e6850989ffd7e9d1 | | `ExternalAccountRegistry` | `celoTest` | 0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc | 0xdec39d8ca0dc8bfdc627a7c1f97d9dd3697c53c6f39ed4824e2a199fb987c8fe | | `ExternalAccountRegistry` | `optimismGoerli` | [0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc](https://goerli-optimism.etherscan.io/address/0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc) | [0x875d088a8e76a15391931ed02980956d65a8ae733cea0c873dcad0a4fe0032b3](https://goerli-optimism.etherscan.io/tx/0x875d088a8e76a15391931ed02980956d65a8ae733cea0c873dcad0a4fe0032b3) | -| `ExternalAccountRegistry` | `neonDevnet` | 0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc | 0xd31152fbbb7e51f8ecdc84610a8c9c099cfd4995ea2f1f4a005a14318f12fcef | +| `ExternalAccountRegistry` | `neonDevnet` | [0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc](https://neonscan.org/address/0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc) | [0x09f8e8b154df9a1b6dd2524ed22f233c717f114e8c5f69f8efbb62822d2843ab](https://neonscan.org/tx/0x09f8e8b154df9a1b6dd2524ed22f233c717f114e8c5f69f8efbb62822d2843ab) | | `ExternalAccountRegistry` | `arbitrumNova` | 0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc | 0x3f1964b962f1b259400e87b32214ae4f6031f17c3e2e5386151030e5e0b124f3 | | `ExternalAccountRegistry` | `arbitrumNitro` | 0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc | 0x8865d755782e210b3a71afba0d372d8cc1504ad47d0dae7fb97020ff5c29424a | | `ExternalAccountRegistry` | `etherspot` | 0x502BbBcC044d2B146c310eB24E5cd8Eba37EdbEc | 0x0bec371bae9679a3eacab911686c48199f620c9f795d9cc5d5faec6f4ab0c669 | @@ -280,7 +280,7 @@ | `Gateway` | `celo` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0x9f0a37c40e438898b92eb3404726cf7e3ab0566e3bd97453153d4502255f15d3 | | `Gateway` | `celoTest` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0x017b93cfff9bef60d74ed3f678617e31bce472a62c16e4170d27833d265295a6 | | `Gateway` | `optimismGoerli` | [0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163](https://goerli-optimism.etherscan.io/address/0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163) | [0xd801f2f0269aad2f10a975734d01b11ed642397969b281d8b3b9b85c84e785c5](https://goerli-optimism.etherscan.io/tx/0xd801f2f0269aad2f10a975734d01b11ed642397969b281d8b3b9b85c84e785c5) | -| `Gateway` | `neonDevnet` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0x527b68d567e57e392dc2f25c13b067067ef03c7870f287b8eb0e3ade6aae7dbb | +| `Gateway` | `neonDevnet` | [0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163](https://neonscan.org/address/0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163) | [0x69796207b7731aa6b5ba6f2b523ccc96829c984b00bbf003e3c569a4afbfa533](https://neonscan.org/tx/0x69796207b7731aa6b5ba6f2b523ccc96829c984b00bbf003e3c569a4afbfa533) | | `Gateway` | `arbitrumNova` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0x79ff0dafd337c73d39c67bd8333fc6524df7690c879f8796789cb58f20c19f4a | | `Gateway` | `arbitrumNitro` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0x36f8325ad8033f74aaf44f3b83a5793928723d9af70eac918eaa8a288d1ab3e5 | | `Gateway` | `etherspot` | 0x432defD2b3733e6fEBb1bD4B17Ed85D15b882163 | 0xba898531d95380c97307201fb1fe773801fb83343d9096c6bc4380402ed4486b | @@ -293,6 +293,7 @@ | `GatewayV2` | `fuji` | [0x9FC4DdE698E5cf1Ee8d6e2D25c835836d9af1C8F](https://testnet.snowtrace.io/address/0x9FC4DdE698E5cf1Ee8d6e2D25c835836d9af1C8F) | [0x8db8b0e7e1e833d4b9ef812bf06fb7338ac25b496447512b5677436a4640a8d0](https://testnet.snowtrace.io/tx/0x8db8b0e7e1e833d4b9ef812bf06fb7338ac25b496447512b5677436a4640a8d0) | | `GatewayV2` | `arbitrumTest` | 0xBEd52610518788B931f7825301909e7616273d47 | 0x12a452e4cf52ed74b5c7baab0581cc622661636c1f0b12be016b85765395af4a | | `GatewayV2` | `optimismGoerli` | [0xBEd52610518788B931f7825301909e7616273d47](https://goerli-optimism.etherscan.io/address/0xBEd52610518788B931f7825301909e7616273d47) | [0x659d06bcb7ae7250cdd02a00f77ece400a29a9ba0ba29ce0073f7b151cb3e9e5](https://goerli-optimism.etherscan.io/tx/0x659d06bcb7ae7250cdd02a00f77ece400a29a9ba0ba29ce0073f7b151cb3e9e5) | +| `GatewayV2` | `neonDevnet` | [0xBEd52610518788B931f7825301909e7616273d47](https://neonscan.org/address/0xBEd52610518788B931f7825301909e7616273d47) | [0xd47dd109531267312897c3af0f325133fa8b87204755426bb1559a721c72f183](https://neonscan.org/tx/0xd47dd109531267312897c3af0f325133fa8b87204755426bb1559a721c72f183) | | `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) | @@ -333,7 +334,7 @@ | `PaymentRegistry` | `celo` | 0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312 | 0x70b6d0b59d9ca6cfc0a02f04742a91177f87166cfe4c287edd08170519390479 | | `PaymentRegistry` | `celoTest` | 0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312 | 0x82b9aa071e80bfb8521d76e0867035116153ee3f9e6d2ba49fd6ac2953d130bb | | `PaymentRegistry` | `optimismGoerli` | [0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312](https://goerli-optimism.etherscan.io/address/0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312) | [0x6d8f012a4112ff01677a80111eda6799be315dba34a22032d213f95e50ffd806](https://goerli-optimism.etherscan.io/tx/0x6d8f012a4112ff01677a80111eda6799be315dba34a22032d213f95e50ffd806) | -| `PaymentRegistry` | `neonDevnet` | 0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312 | 0x23514b60607e2f59c56170f5a4b9060b03c153224c94f0cd0332e08edf27e019 | +| `PaymentRegistry` | `neonDevnet` | [0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312](https://neonscan.org/address/0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312) | [0x87a6e9c662c740c36c83bd275c030f7de9f40bfeb9963a45a201bce5eb833ac3](https://neonscan.org/tx/0x87a6e9c662c740c36c83bd275c030f7de9f40bfeb9963a45a201bce5eb833ac3) | | `PaymentRegistry` | `arbitrumNova` | 0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312 | 0xb7ec876ed6042538461dfaf4d7e492be17b5448fe07671160d82d9963f7c777e | | `PaymentRegistry` | `arbitrumNitro` | 0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312 | 0x805266d618015606750cbd0e794ef1420e7abed5584c7eb10dd2634c252eb0ec | | `PaymentRegistry` | `etherspot` | 0xB6900522DC23F3cdAeA61bf0Ca17a672b8Dbe312 | 0x96338b94bbc9fe24b6e5def6ad523983dfd56883620a85ebd4ca35d0be609d0c | @@ -365,7 +366,7 @@ | `PersonalAccountImplementationV1` | `celo` | 0x0672aF0018fdEbACcc93c7D047D62b72CB12883A | 0x0816d1e8803abb1a638e1aba5ec7395e5cd8228d2883cc3d7c1ea2af19fc0926 | | `PersonalAccountImplementationV1` | `celoTest` | 0x0672aF0018fdEbACcc93c7D047D62b72CB12883A | 0xbf4e974badd253ba96904e2281d01ac7e00ac798763568581b3674cf3e6df5df | | `PersonalAccountImplementationV1` | `optimismGoerli` | [0x0672aF0018fdEbACcc93c7D047D62b72CB12883A](https://goerli-optimism.etherscan.io/address/0x0672aF0018fdEbACcc93c7D047D62b72CB12883A) | [0xcffd93857acca4e772c09d3754aea78b35120ecc0d6916c79666c1aaded3ae67](https://goerli-optimism.etherscan.io/tx/0xcffd93857acca4e772c09d3754aea78b35120ecc0d6916c79666c1aaded3ae67) | -| `PersonalAccountImplementationV1` | `neonDevnet` | 0x0672aF0018fdEbACcc93c7D047D62b72CB12883A | 0x620748c84602085f064e8d9453530f6425c1a27cc17c13c881d797735cd4573f | +| `PersonalAccountImplementationV1` | `neonDevnet` | [0x0672aF0018fdEbACcc93c7D047D62b72CB12883A](https://neonscan.org/address/0x0672aF0018fdEbACcc93c7D047D62b72CB12883A) | [0x9eac853d1f5dd68d67492171a94ac4807499e1b0310ce92f981052a1696eeb51](https://neonscan.org/tx/0x9eac853d1f5dd68d67492171a94ac4807499e1b0310ce92f981052a1696eeb51) | | `PersonalAccountImplementationV1` | `arbitrumNova` | 0x0672aF0018fdEbACcc93c7D047D62b72CB12883A | 0x0bb5a57e646f35b1a2d9dffb012a3116206cd17ca18768f4b29af1d90ebfd37c | | `PersonalAccountImplementationV1` | `arbitrumNitro` | 0x0672aF0018fdEbACcc93c7D047D62b72CB12883A | 0x41e4b313037c8579d3a5da6d041d488df6fd41232892bbd2eb8510e41d82e73d | | `PersonalAccountImplementationV1` | `etherspot` | 0x0672aF0018fdEbACcc93c7D047D62b72CB12883A | 0x8ddcf689ffc89e45538b31941069088c0a63d34de0f24358cd29f536e8dce3e2 | @@ -397,7 +398,7 @@ | `PersonalAccountRegistry` | `celo` | 0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa | 0x2a601f05cdc7d98281ce20575ba214505f325a9bc3a938c5255fa7a44fab39c5 | | `PersonalAccountRegistry` | `celoTest` | 0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa | 0x1462730017894782a39811340aa50ec65a2a9ad710f6a38de578ed7fc44e4b73 | | `PersonalAccountRegistry` | `optimismGoerli` | [0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa](https://goerli-optimism.etherscan.io/address/0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa) | [0xf3b0aba701b3ccc2ebff11293d61972aed0c29416388a027f0d56daac6c53415](https://goerli-optimism.etherscan.io/tx/0xf3b0aba701b3ccc2ebff11293d61972aed0c29416388a027f0d56daac6c53415) | -| `PersonalAccountRegistry` | `neonDevnet` | 0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa | 0x2a0d6342070736407eb6a3ddf0775e9b7e4c8e67ca488916a7f6b88e195fa89c | +| `PersonalAccountRegistry` | `neonDevnet` | [0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa](https://neonscan.org/address/0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa) | [0x500168d580eb4a23db0cb3a14778177d89872e68bbaf74d21c0bb5424ba48ef9](https://neonscan.org/tx/0x500168d580eb4a23db0cb3a14778177d89872e68bbaf74d21c0bb5424ba48ef9) | | `PersonalAccountRegistry` | `arbitrumNova` | 0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa | 0xeb6718d5a1810061bc558f304417e667c8a03c03137903911bf48b60be7369ad | | `PersonalAccountRegistry` | `arbitrumNitro` | 0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa | 0x6779c8aff1b896b2228fd9248f244902ce6e7629b35eb962d862ffaca47a2851 | | `PersonalAccountRegistry` | `etherspot` | 0x7EB3A038F25B9F32f8e19A7F0De83D4916030eFa | 0xd9359a5aa653ba4acab01ad38a2cb644f2140f0d7d1648398414471422448346 | @@ -432,7 +433,7 @@ | `WrappedWeiToken` | `celo` | 0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616 | 0x81141ef3b78568d3c8889b4f4443868dd3766cd08b9eac34a5b8030c29636321 | | `WrappedWeiToken` | `celoTest` | 0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616 | 0xda0092889e56a998075e66d89d03e6f0f54382e43780adb837dc0ffac6f56b16 | | `WrappedWeiToken` | `optimismGoerli` | [0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616](https://goerli-optimism.etherscan.io/address/0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616) | [0xa10b0b346de9df45e23f0f1a09ab84264ba3aec157c847d19b3412c46a0cf70b](https://goerli-optimism.etherscan.io/tx/0xa10b0b346de9df45e23f0f1a09ab84264ba3aec157c847d19b3412c46a0cf70b) | -| `WrappedWeiToken` | `neonDevnet` | 0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616 | 0x914aca830634bfd34953e0964b78873ddce6d6c0a62161b7a5501b4b5ca196f5 | +| `WrappedWeiToken` | `neonDevnet` | [0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616](https://neonscan.org/address/0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616) | [0x3da6fb813eb5a300a50d8fcd9e77655806bde218175c7187c05d0e36042b6348](https://neonscan.org/tx/0x3da6fb813eb5a300a50d8fcd9e77655806bde218175c7187c05d0e36042b6348) | | `WrappedWeiToken` | `arbitrumNova` | 0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616 | 0xaf496abf9b16e972369caf27ba70333c7eaee148f292af095374f067547aa8d3 | | `WrappedWeiToken` | `arbitrumNitro` | 0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616 | 0x990f502ea7ba7f8e5c3258281cb43e833aa7d040909cada623bc9417100f2460 | | `WrappedWeiToken` | `etherspot` | 0x8e5ea4368fcd17A4efF851C5ffa6cd03bBDeb616 | 0x97561b8070bdcb84cc0ef0fc47a1f59ebe56c36e3f7448e90e39cdcd65aefd9d | diff --git a/deployments/neonDevnet/BalancesHelper.json b/deployments/neonDevnet/BalancesHelper.json index 85107924..22eda34f 100644 --- a/deployments/neonDevnet/BalancesHelper.json +++ b/deployments/neonDevnet/BalancesHelper.json @@ -26,7 +26,7 @@ "type": "function" } ], - "transactionHash": "0x154f16bb095d820f6e20d631b2e7df8d0e3f1a82732e4ea463b5584cbb37ecd9", + "transactionHash": "0x1ace0e0cbe0344d55bbfbc5a94a7e1a9a309f2442c8b4146af639af99249c84e", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -34,16 +34,16 @@ "transactionIndex": 0, "gasUsed": "28969680", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x483c0623530c29e53fc4515f604af3512f1ce74497a8bab65e23827992fff04a", - "transactionHash": "0x154f16bb095d820f6e20d631b2e7df8d0e3f1a82732e4ea463b5584cbb37ecd9", + "blockHash": "0xfb816ac331fa0b0a293785f67443eb81a59dfb5b0ef446f9b1e3014d2c1044a6", + "transactionHash": "0x1ace0e0cbe0344d55bbfbc5a94a7e1a9a309f2442c8b4146af639af99249c84e", "logs": [], - "blockNumber": 173996669, + "blockNumber": 178554930, "cumulativeGasUsed": "28969680", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"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\"}],\"devdoc\":{\"author\":\"Jegor Sidorenko Stanis\\u0142aw G\\u0142ogowski \",\"kind\":\"dev\",\"methods\":{\"getBalances(address[],address[])\":{\"details\":\"Pass 0x0 as a \\\"token\\\" address to get ETH balance. Possible error throws: - extremely large arrays for account and or tokens (gas cost too high)\",\"params\":{\"accounts\":\"array of accounts addresses\",\"tokens\":\"array of tokens addresses\"},\"returns\":{\"_0\":\"a one-dimensional that's user.length * tokens.length long. The array is ordered by all of the 0th accounts token balances, then the 1th user, and so on.\"}}},\"title\":\"Balances helper\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getBalances(address[],address[])\":{\"notice\":\"Checks the token balances of accounts for multiple tokens.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/common/helpers/BalancesHelper.sol\":\"BalancesHelper\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/common/helpers/BalancesHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../token/ERC20Token.sol\\\";\\nimport \\\"../libs/SafeMathLib.sol\\\";\\n\\n\\n/**\\n * @title Balances helper\\n *\\n * @author Jegor Sidorenko \\n * @author Stanis\\u0142aw G\\u0142ogowski \\n */\\ncontract BalancesHelper {\\n using SafeMathLib for uint256;\\n\\n // external functions\\n\\n /**\\n * @notice Checks the token balances of accounts for multiple tokens.\\n * @dev Pass 0x0 as a \\\"token\\\" address to get ETH balance.\\n *\\n * Possible error throws:\\n * - extremely large arrays for account and or tokens (gas cost too high)\\n *\\n * @param accounts array of accounts addresses\\n * @param tokens array of tokens addresses\\n * @return a one-dimensional that's user.length * tokens.length long. The\\n * array is ordered by all of the 0th accounts token balances, then the 1th\\n * user, and so on.\\n */\\n function getBalances(\\n address[] calldata accounts,\\n address[] calldata tokens\\n )\\n external\\n view\\n returns (uint[] memory)\\n {\\n uint[] memory result = new uint[](accounts.length.mul(tokens.length));\\n\\n for (uint i = 0; i < accounts.length; i++) {\\n for (uint j = 0; j < tokens.length; j++) {\\n uint index = j.add(tokens.length.mul(i));\\n\\n if (tokens[j] != address(0x0)) {\\n result[index] = _getBalance(accounts[i], tokens[j]);\\n } else {\\n result[index] = accounts[i].balance;\\n }\\n }\\n }\\n\\n return result;\\n }\\n\\n // private functions\\n\\n function _getBalance(\\n address account,\\n address token\\n )\\n private\\n view\\n returns (uint256)\\n {\\n uint256 result = 0;\\n uint256 tokenCode;\\n\\n /// @dev check if token is actually a contract\\n // solhint-disable-next-line no-inline-assembly\\n assembly { tokenCode := extcodesize(token) } // contract code size\\n\\n if (tokenCode > 0) {\\n /// @dev is it a contract and does it implement balanceOf\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool methodExists,) = token.staticcall(abi.encodeWithSelector(\\n ERC20Token(token).balanceOf.selector,\\n account\\n ));\\n\\n if (methodExists) {\\n result = ERC20Token(token).balanceOf(account);\\n }\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x76a5729807b8581731967ea74fc5e16a2c5c9067457c9059da97f089ffff68b9\",\"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/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\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b506106a2806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063ef5bfc3714610030575b600080fd5b6100fc6004803603604081101561004657600080fd5b810190808035906020019064010000000081111561006357600080fd5b82018360208201111561007557600080fd5b8035906020019184602083028401116401000000008311171561009757600080fd5b9091929391929390803590602001906401000000008111156100b857600080fd5b8201836020820111156100ca57600080fd5b803590602001918460208302840111640100000000831117156100ec57600080fd5b9091929391929390505050610153565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561013f578082015181840152602081019050610124565b505050509050019250505060405180910390f35b60608061016f848490508787905061035490919063ffffffff16565b67ffffffffffffffff8111801561018557600080fd5b506040519080825280602002602001820160405280156101b45781602001602082028036833780820191505090505b50905060005b868690508110156103475760005b858590508110156103395760006101fd6101ee848989905061035490919063ffffffff16565b836103da90919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff1687878481811061022357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146102d2576102b589898581811061026a57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1688888581811061029357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16610462565b8482815181106102c157fe5b60200260200101818152505061032b565b8888848181106102de57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163184828151811061031e57fe5b6020026020010181815250505b5080806001019150506101c8565b5080806001019150506101ba565b5080915050949350505050565b60008083141561036757600090506103d4565b600082840290508284828161037857fe5b04146103cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806106726024913960400191505060405180910390fd5b809150505b92915050565b600080828401905083811015610458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174684c69623a206164646974696f6e206f766572666c6f77000081525060200191505060405180910390fd5b8091505092915050565b600080600090506000833b905060008111156106665760008473ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b87604051602401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310610550578051825260208201915060208101905060208303925061052d565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146105b0576040519150601f19603f3d011682016040523d82523d6000602084013e6105b5565b606091505b505090508015610664578473ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561062657600080fd5b505afa15801561063a573d6000803e3d6000fd5b505050506040513d602081101561065057600080fd5b810190808051906020019092919050505092505b505b81925050509291505056fe536166654d6174684c69623a206d756c7469706c69636174696f6e206f766572666c6f77a164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063ef5bfc3714610030575b600080fd5b6100fc6004803603604081101561004657600080fd5b810190808035906020019064010000000081111561006357600080fd5b82018360208201111561007557600080fd5b8035906020019184602083028401116401000000008311171561009757600080fd5b9091929391929390803590602001906401000000008111156100b857600080fd5b8201836020820111156100ca57600080fd5b803590602001918460208302840111640100000000831117156100ec57600080fd5b9091929391929390505050610153565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561013f578082015181840152602081019050610124565b505050509050019250505060405180910390f35b60608061016f848490508787905061035490919063ffffffff16565b67ffffffffffffffff8111801561018557600080fd5b506040519080825280602002602001820160405280156101b45781602001602082028036833780820191505090505b50905060005b868690508110156103475760005b858590508110156103395760006101fd6101ee848989905061035490919063ffffffff16565b836103da90919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff1687878481811061022357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146102d2576102b589898581811061026a57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1688888581811061029357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16610462565b8482815181106102c157fe5b60200260200101818152505061032b565b8888848181106102de57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163184828151811061031e57fe5b6020026020010181815250505b5080806001019150506101c8565b5080806001019150506101ba565b5080915050949350505050565b60008083141561036757600090506103d4565b600082840290508284828161037857fe5b04146103cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806106726024913960400191505060405180910390fd5b809150505b92915050565b600080828401905083811015610458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174684c69623a206164646974696f6e206f766572666c6f77000081525060200191505060405180910390fd5b8091505092915050565b600080600090506000833b905060008111156106665760008473ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b87604051602401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310610550578051825260208201915060208101905060208303925061052d565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146105b0576040519150601f19603f3d011682016040523d82523d6000602084013e6105b5565b606091505b505090508015610664578473ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561062657600080fd5b505afa15801561063a573d6000803e3d6000fd5b505050506040513d602081101561065057600080fd5b810190808051906020019092919050505092505b505b81925050509291505056fe536166654d6174684c69623a206d756c7469706c69636174696f6e206f766572666c6f77a164736f6c634300060c000a", diff --git a/deployments/neonDevnet/BalancesHelperV2.json b/deployments/neonDevnet/BalancesHelperV2.json index 4fc953a2..9de4e7ef 100644 --- a/deployments/neonDevnet/BalancesHelperV2.json +++ b/deployments/neonDevnet/BalancesHelperV2.json @@ -87,7 +87,7 @@ "type": "function" } ], - "transactionHash": "0xf1b8cb6bbef86256c57e6ea7b672377a8ea4033e556da2b781203cc4e7bf97d5", + "transactionHash": "0xb3723d3c80a4ba1370984041779b7dab86056a8624c31b11970ba2dbc959f96f", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -95,16 +95,16 @@ "transactionIndex": 0, "gasUsed": "48826560", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x22a1e46582c7b9544b3001f90c5e0b3066b2f51e28feadc055d316907cdd1d5f", - "transactionHash": "0xf1b8cb6bbef86256c57e6ea7b672377a8ea4033e556da2b781203cc4e7bf97d5", + "blockHash": "0x565635ff49493ebf7f3c078e3672c7e4e8a52637771e3436e61440d68c829608", + "transactionHash": "0xb3723d3c80a4ba1370984041779b7dab86056a8624c31b11970ba2dbc959f96f", "logs": [], - "blockNumber": 173996704, + "blockNumber": 178554973, "cumulativeGasUsed": "48826560", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "82f81c73c615e1d8d0ff013db621d6da", + "solcInputHash": "6ff48c01406545b171c1098ac74d4555", "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\\n// solhint-disable-next-line\\npragma solidity 0.8.4;\\n\\n/// @title BalancesHelperV2\\n/// @author Luke Wickens \\n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\\n\\nimport {ISuperfluidToken} from \\\"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/interfaces/IERC20.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\ncontract BalancesHelperV2 {\\n using Address for address;\\n\\n /// @notice Custom errors to handle address(0)\\n error AccountZeroAddress(address account, address token);\\n error TokenZeroAddress(address account, address token);\\n\\n constructor() {}\\n\\n /// @notice Returns balances of accounts for multiple ERC20 tokens.\\n /// @dev Error thrown if: account or token address is address(0),\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\n /// @param accounts = Array of accounts addresses\\n /// @param tokens = Array of tokens addresses\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\n\\n function getBalances(address[] calldata accounts, address[] calldata tokens)\\n external\\n view\\n returns (uint256[] memory)\\n {\\n uint256[] memory result = new uint256[](\\n accounts.length * tokens.length\\n );\\n\\n for (uint256 i; i < accounts.length; i++) {\\n for (uint256 j; j < tokens.length; j++) {\\n uint256 index = j + (tokens.length * i);\\n result[index] = _getBalance(accounts[i], tokens[j]);\\n }\\n }\\n return result;\\n }\\n\\n /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\\n /// @dev Error thrown if: account or token address is address(0),\\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\\n /// @param accounts = Array of accounts addresses\\n /// @param tokens = Array of tokens addresses\\n /// @return One-dimensional that's accounts.length * tokens.length long. The\\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\\n\\n function getSuperfluidWrappedTokenBalances(\\n address[] calldata accounts,\\n address[] calldata tokens\\n ) external view returns (int256[] memory) {\\n int256[] memory result = new int256[](accounts.length * tokens.length);\\n\\n for (uint256 i; i < accounts.length; i++) {\\n for (uint256 j; j < tokens.length; j++) {\\n uint256 index = j + (tokens.length * i);\\n result[index] = _getSuperfluidWrappedTokenBalance(\\n accounts[i],\\n tokens[j]\\n );\\n }\\n }\\n return result;\\n }\\n\\n /// Private fuctions\\n\\n /// @notice Returns balance of account for an ERC20 token.\\n /// @dev Error thrown if: account or token address is address(0)\\n /// @param account = account address\\n /// @param token = tokens address\\n /// @return balance of account as uint256.\\n\\n function _getBalance(address account, address token)\\n private\\n view\\n returns (uint256)\\n {\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\n\\n bytes memory returnedData = token.functionStaticCall(\\n abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\\n );\\n\\n return abi.decode(returnedData, (uint256));\\n }\\n\\n /// @notice Returns real balance of a user, taking into consideration all agreements of account\\n /// @dev Error thrown if: account or token address is address(0)\\n /// @param account = account address\\n /// @param token = tokens address\\n /// @return available balance of account as int256.\\n\\n function _getSuperfluidWrappedTokenBalance(address account, address token)\\n private\\n view\\n returns (int256)\\n {\\n if (account == address(0)) revert AccountZeroAddress(account, token);\\n if (token == address(0)) revert TokenZeroAddress(account, token);\\n\\n bytes memory returnedData = token.functionStaticCall(\\n abi.encodeWithSelector(\\n ISuperfluidToken(token).realtimeBalanceOfNow.selector,\\n account\\n )\\n );\\n\\n (int256 availableBalance, , , ) = abi.decode(\\n returnedData,\\n (int256, uint256, uint256, uint256)\\n );\\n return availableBalance;\\n }\\n}\\n\",\"keccak256\":\"0x02dfe13a8521bebc6f623a9df9877d7c66f8cfb67c10ee1a041dcba42ef7b973\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b5061108a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806350c5a7101461003b578063ef5bfc371461006b575b600080fd5b610055600480360381019061005091906109e6565b61009b565b6040516100629190610ce8565b60405180910390f35b610085600480360381019061008091906109e6565b610279565b6040516100929190610d0a565b60405180910390f35b6060600083839050868690506100b19190610e68565b67ffffffffffffffff8111156100f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561011e5781602001602082028036833780820191505090505b50905060005b8686905081101561026c5760005b85859050811015610258576000828787905061014e9190610e68565b826101599190610e12565b90506101ff898985818110610197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101ac91906109bd565b8888858181106101e5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101fa91906109bd565b610457565b848281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061025090610f3b565b915050610132565b50808061026490610f3b565b915050610124565b5080915050949350505050565b60606000838390508686905061028f9190610e68565b67ffffffffffffffff8111156102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156102fc5781602001602082028036833780820191505090505b50905060005b8686905081101561044a5760005b85859050811015610436576000828787905061032c9190610e68565b826103379190610e12565b90506103dd898985818110610375577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b905060200201602081019061038a91906109bd565b8888858181106103c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906103d891906109bd565b610608565b848281518110610416577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505050808061042e90610f3b565b915050610310565b50808061044290610f3b565b915050610302565b5080915050949350505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156104cc5782826040517f484305ff0000000000000000000000000000000000000000000000000000000081526004016104c3929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156105405782826040517f41f93bdf000000000000000000000000000000000000000000000000000000008152600401610537929190610cbf565b60405180910390fd5b60006105e0632ec8eec760e01b8560405160240161055e9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b90506000818060200190518101906105f89190610a5b565b5050509050809250505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561067d5782826040517f484305ff000000000000000000000000000000000000000000000000000000008152600401610674929190610cbf565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106f15782826040517f41f93bdf0000000000000000000000000000000000000000000000000000000081526004016106e8929190610cbf565b60405180910390fd5b60006107916370a0823160e01b8560405160240161070f9190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050508473ffffffffffffffffffffffffffffffffffffffff166107b090919063ffffffff16565b9050808060200190518101906107a79190610abe565b91505092915050565b60606107d58383604051806060016040528060258152602001611059602591396107dd565b905092915050565b60606107e8846108aa565b610827576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081e90610d4e565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161084f9190610c8d565b600060405180830381855afa9150503d806000811461088a576040519150601f19603f3d011682016040523d82523d6000602084013e61088f565b606091505b509150915061089f8282866108cd565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606083156108dd5782905061092d565b6000835111156108f05782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109249190610d2c565b60405180910390fd5b9392505050565b60008135905061094381611013565b92915050565b60008083601f84011261095b57600080fd5b8235905067ffffffffffffffff81111561097457600080fd5b60208301915083602082028301111561098c57600080fd5b9250929050565b6000815190506109a28161102a565b92915050565b6000815190506109b781611041565b92915050565b6000602082840312156109cf57600080fd5b60006109dd84828501610934565b91505092915050565b600080600080604085870312156109fc57600080fd5b600085013567ffffffffffffffff811115610a1657600080fd5b610a2287828801610949565b9450945050602085013567ffffffffffffffff811115610a4157600080fd5b610a4d87828801610949565b925092505092959194509250565b60008060008060808587031215610a7157600080fd5b6000610a7f87828801610993565b9450506020610a90878288016109a8565b9350506040610aa1878288016109a8565b9250506060610ab2878288016109a8565b91505092959194509250565b600060208284031215610ad057600080fd5b6000610ade848285016109a8565b91505092915050565b6000610af38383610c13565b60208301905092915050565b6000610b0b8383610c7e565b60208301905092915050565b610b2081610ec2565b82525050565b6000610b3182610d8e565b610b3b8185610dd4565b9350610b4683610d6e565b8060005b83811015610b77578151610b5e8882610ae7565b9750610b6983610dba565b925050600181019050610b4a565b5085935050505092915050565b6000610b8f82610d99565b610b998185610de5565b9350610ba483610d7e565b8060005b83811015610bd5578151610bbc8882610aff565b9750610bc783610dc7565b925050600181019050610ba8565b5085935050505092915050565b6000610bed82610da4565b610bf78185610df6565b9350610c07818560208601610f08565b80840191505092915050565b610c1c81610ed4565b82525050565b6000610c2d82610daf565b610c378185610e01565b9350610c47818560208601610f08565b610c5081610fb3565b840191505092915050565b6000610c68602483610e01565b9150610c7382610fc4565b604082019050919050565b610c8781610efe565b82525050565b6000610c998284610be2565b915081905092915050565b6000602082019050610cb96000830184610b17565b92915050565b6000604082019050610cd46000830185610b17565b610ce16020830184610b17565b9392505050565b60006020820190508181036000830152610d028184610b26565b905092915050565b60006020820190508181036000830152610d248184610b84565b905092915050565b60006020820190508181036000830152610d468184610c22565b905092915050565b60006020820190508181036000830152610d6781610c5b565b9050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000610e1d82610efe565b9150610e2883610efe565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610e5d57610e5c610f84565b5b828201905092915050565b6000610e7382610efe565b9150610e7e83610efe565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb6610f84565b5b828202905092915050565b6000610ecd82610ede565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610f26578082015181840152602081019050610f0b565b83811115610f35576000848401525b50505050565b6000610f4682610efe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610f7957610f78610f84565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000601f19601f8301169050919050565b7f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460008201527f7261637400000000000000000000000000000000000000000000000000000000602082015250565b61101c81610ec2565b811461102757600080fd5b50565b61103381610ed4565b811461103e57600080fd5b50565b61104a81610efe565b811461105557600080fd5b5056fe416464726573733a206c6f772d6c6576656c207374617469632063616c6c206661696c6564a164736f6c6343000804000a", diff --git a/deployments/neonDevnet/ENSController.json b/deployments/neonDevnet/ENSController.json index 47cb6bc6..c14dd1d5 100644 --- a/deployments/neonDevnet/ENSController.json +++ b/deployments/neonDevnet/ENSController.json @@ -756,7 +756,7 @@ "type": "function" } ], - "transactionHash": "0x24da3b71a66b5ecbc9ae73762d856309525b4e69d7735977b2e29f9f443c7869", + "transactionHash": "0x3e4a01a335da80d736867d8b00c38fe99d39affa6eb741f61cfe4307ce33a2f6", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -764,16 +764,16 @@ "transactionIndex": 0, "gasUsed": "162959680", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8cdaa81ead76fca6b7464a70318656cb2a4df6f7f6b1bc403a8598a11642fb29", - "transactionHash": "0x24da3b71a66b5ecbc9ae73762d856309525b4e69d7735977b2e29f9f443c7869", + "blockHash": "0x647623e25a3bf0de680216941283aa064a6504a83259685e9a1da344b1fee220", + "transactionHash": "0x3e4a01a335da80d736867d8b00c38fe99d39affa6eb741f61cfe4307ce33a2f6", "logs": [], - "blockNumber": 173996763, + "blockNumber": 178555027, "cumulativeGasUsed": "162959680", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newAddress\",\"type\":\"bytes\"}],\"name\":\"AddressChanged\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NodeReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NodeSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"NodeVerified\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"RegistryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"addGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"label\",\"type\":\"bytes32\"}],\"internalType\":\"struct ENSController.SubNodeRegistration\",\"name\":\"subNodeRegistration\",\"type\":\"tuple\"}],\"name\":\"hashSubNodeRegistration\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ENSRegistry\",\"name\":\"registry_\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"guardians_\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"gateway_\",\"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\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"nodeOwners\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"label\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"guardianSignature\",\"type\":\"bytes\"}],\"name\":\"registerSubNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"contract ENSRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"releaseNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"removeGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"addr_\",\"type\":\"bytes\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ENSRegistry\",\"name\":\"registry_\",\"type\":\"address\"}],\"name\":\"setRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"setText\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"submitNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"syncAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"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\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"verifyNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"details\":\"The process of adding root node consists of 3 steps: 1. `submitNode` - should be called from ENS node owner, 2. Change ENS node owner in ENS registry to ENS controller, 3. `verifyNode` - should be called from previous ENS node owner, To register sub node, `msg.sender` need to send valid signature from one of guardian key. Once registration is complete `msg.sender` becoming both node owner and `addr` record value. After registration sub node cannot be replaced.\",\"events\":{\"NodeReleased(bytes32,address)\":{\"details\":\"Emitted when new node is released\",\"params\":{\"node\":\"node name hash\",\"owner\":\"owner address\"}},\"NodeSubmitted(bytes32,address)\":{\"details\":\"Emitted when new node is submitted\",\"params\":{\"node\":\"node name hash\",\"owner\":\"owner address\"}},\"NodeVerified(bytes32)\":{\"details\":\"Emitted when the existing owner is verified\",\"params\":{\"node\":\"node name hash\"}},\"RegistryChanged(address)\":{\"details\":\"Emitted when ENS registry address is changed\",\"params\":{\"registry\":\"registry address\"}}},\"kind\":\"dev\",\"methods\":{\"addGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"constructor\":{\"details\":\"Public constructor\"},\"hashSubNodeRegistration((address,bytes32,bytes32))\":{\"params\":{\"subNodeRegistration\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"initialize(address,address[],address)\":{\"params\":{\"gateway_\":\"gateway address\",\"registry_\":\"ENS registry address\"}},\"isGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"},\"returns\":{\"_0\":\"true when guardian exists\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"registerSubNode(bytes32,bytes32,bytes)\":{\"params\":{\"guardianSignature\":\"guardian signature\",\"label\":\"label hash\",\"node\":\"node name hash\"}},\"releaseNode(bytes32)\":{\"details\":\"Should be called from the previous ENS node owner\",\"params\":{\"node\":\"node name hash\"}},\"removeGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"setRegistry(address)\":{\"params\":{\"registry_\":\"registry address\"}},\"submitNode(bytes32)\":{\"details\":\"Should be called from the current ENS node owner\",\"params\":{\"node\":\"node name hash\"}},\"syncAddr(bytes32)\":{\"params\":{\"node\":\"node name hash\"}},\"verifyGuardianSignature(bytes32,bytes)\":{\"params\":{\"messageHash\":\"message hash\",\"signature\":\"signature\"},\"returns\":{\"_0\":\"true on correct guardian signature\"}},\"verifyNode(bytes32)\":{\"details\":\"Should be called from the previous ENS node owner\",\"params\":{\"node\":\"node name hash\"}}},\"title\":\"ENS controller\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addGuardian(address)\":{\"notice\":\"Adds a new guardian\"},\"hashSubNodeRegistration((address,bytes32,bytes32))\":{\"notice\":\"Hashes `SubNodeRegistration` message payload\"},\"initialize(address,address[],address)\":{\"notice\":\"Initializes `ENSController` contract\"},\"isGuardian(address)\":{\"notice\":\"Check if guardian exists\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"registerSubNode(bytes32,bytes32,bytes)\":{\"notice\":\"Registers sub node\"},\"releaseNode(bytes32)\":{\"notice\":\"Releases node\"},\"removeGuardian(address)\":{\"notice\":\"Removes the existing guardian\"},\"setRegistry(address)\":{\"notice\":\"Sets registry\"},\"submitNode(bytes32)\":{\"notice\":\"Submits node\"},\"syncAddr(bytes32)\":{\"notice\":\"Sync address\"},\"verifyGuardianSignature(bytes32,bytes)\":{\"notice\":\"Verifies guardian signature\"},\"verifyNode(bytes32)\":{\"notice\":\"Verifies node\"}},\"notice\":\"ENS subnode registrar\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ens/ENSController.sol\":\"ENSController\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"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/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/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/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/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\\u0142aw G\\u0142ogowski \\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\",\"keccak256\":\"0x8006c066bef9625f3d103d77e8b66ff5f006187586cd4518676e73c5d3f79957\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xe00dbdea09d17d41c2c14266e6e1b6b95938c0d374b266bb44a91cfcf0495612\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xc67d8bdd4904684e5d3388f7ca7d18c7d407058d6b548d8c591404c758a1ac60\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xd2f0c5ed5f5058755512c0916496da6bcf4cf18a0026ee8d20b4306656ce5142\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x1d2d4b21f59225fbefe0e5aaff87aff8f11afe5281745934d595e15770557ead\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x763a3403ded734b7fa9141c270a0aaaf4a3f1322ff4b197e51ed70adfbaf1fa1\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x6d13447ff9aa753320b3a93ba0b8a2cbb43385711d51e00809cfb9201136cff7\",\"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\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b5032600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600046905080600281905550506149798061006e6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806371404156116100f9578063a91ee0dc11610097578063d0f710d611610071578063d0f710d614610512578063d5fa2b0014610542578063dc5b68a61461055e578063f1cb7e061461057a576101c4565b8063a91ee0dc146104a9578063c8690233146104c5578063c8cc2aee146104f6576101c4565b80637d0e0e7e116100d35780637d0e0e7e146104375780638b95dd71146104535780639a8a05921461046f578063a526d83b1461048d576101c4565b806371404156146103e157806377372213146103fd5780637b10399914610419576101c4565b8063392e53cd1161016657806355800f871161014057806355800f871461033557806359d1d43c14610351578063691f3431146103815780636df0cf42146103b1576101c4565b8063392e53cd146102cb5780633b3b57de146102e957806346386f7314610319576101c4565b8063116191b6116101a2578063116191b6146102455780631b3cd1421461026357806329ae6a7e1461029357806329cd62ea146102af576101c4565b806301ffc9a7146101c95780630c68ba21146101f957806310f13a8c14610229575b600080fd5b6101e360048036038101906101de91906133b4565b6105aa565b6040516101f091906141bc565b60405180910390f35b610213600480360381019061020e9190613066565b610834565b60405161022091906141bc565b60405180910390f35b610243600480360381019061023e9190613288565b610889565b005b61024d61096d565b60405161025a919061415d565b60405180910390f35b61027d600480360381019061027891906130b8565b610993565b60405161028a919061415d565b60405180910390f35b6102ad60048036038101906102a891906130b8565b6109c6565b005b6102c960048036038101906102c4919061311d565b610beb565b005b6102d3610cb3565b6040516102e091906141bc565b60405180910390f35b61030360048036038101906102fe91906130b8565b610d0b565b604051610310919061415d565b60405180910390f35b610333600480360381019061032e919061316c565b610d1d565b005b61034f600480360381019061034a91906130b8565b611017565b005b61036b60048036038101906103669190613230565b6112d8565b604051610378919061433d565b60405180910390f35b61039b600480360381019061039691906130b8565b6113ad565b6040516103a8919061433d565b60405180910390f35b6103cb60048036038101906103c69190613472565b611462565b6040516103d891906141d7565b60405180910390f35b6103fb60048036038101906103f69190613066565b611482565b005b61041760048036038101906104129190613230565b61169a565b005b610421611746565b60405161042e91906142fe565b60405180910390f35b610451600480360381019061044c91906130b8565b61176c565b005b61046d6004803603810190610468919061334d565b611a38565b005b610477611a92565b604051610484919061461f565b60405180910390f35b6104a760048036038101906104a29190613066565b611a98565b005b6104c360048036038101906104be91906133dd565b611b2f565b005b6104df60048036038101906104da91906130b8565b611d58565b6040516104ed92919061421b565b60405180910390f35b610510600480360381019061050b91906130b8565b611d92565b005b61052c600480360381019061052791906131d8565b6120a2565b60405161053991906141bc565b60405180910390f35b61055c600480360381019061055791906130e1565b6120fb565b005b61057860048036038101906105739190613406565b612153565b005b610594600480360381019061058f9190613311565b612366565b6040516105a191906142dc565b60405180910390f35b60006040516020016105bb9061406f565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061067d5750604051602001610626906140aa565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806106e95750604051602001610692906140fe565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061075557506040516020016106fe906140d4565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107c1575060405160200161076a906140e9565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061082d57506040516020016107d6906140bf565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b846108938161242d565b6108d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c9906145df565b60405180910390fd5b82826007600089815260200190815260200160002087876040516108f7929190614056565b90815260200160405180910390209190610912929190612d39565b508484604051610923929190614056565b6040518091039020867fd8c9334b1a9c2f9da342a0a2b32629c1a229b6445dad78947f674b44444a7550878760405161095d929190614319565b60405180910390a3505050505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60096020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006109d0612516565b90503073ffffffffffffffffffffffffffffffffffffffff166109f283612527565b73ffffffffffffffffffffffffffffffffffffffff1614610a48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3f9061443f565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ae9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae09061437f565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635b0fc9c383836040518363ffffffff1660e01b8152600401610b469291906141f2565b600060405180830381600087803b158015610b6057600080fd5b505af1158015610b74573d6000803e3d6000fd5b505050506009600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690557f7803a16d95f9ca635bdec561006625e7444d8a9f8463866643cc03af011779d38282604051610bdf9291906141f2565b60405180910390a15050565b82610bf58161242d565b610c34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2b906145df565b60405180910390fd5b604051806040016040528084815260200183815250600660008681526020019081526020016000206000820151816000015560208201518160010155905050837f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e468484604051610ca592919061421b565b60405180910390a250505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b6000610d1682612527565b9050919050565b6000610d27612516565b90506000610d3682878761260c565b9050610d868185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612664565b610dc5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbc9061439f565b60405180910390fd5b60008686604051602001610dda92919061402a565b6040516020818303038152906040528051906020012090503073ffffffffffffffffffffffffffffffffffffffff16610e1288612527565b73ffffffffffffffffffffffffffffffffffffffff1614610e68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5f9061441f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16610e8982612527565b73ffffffffffffffffffffffffffffffffffffffff1614610edf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed6906143bf565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635ef2c7f08888303060006040518663ffffffff1660e01b8152600401610f43959493929190614244565b600060405180830381600087803b158015610f5d57600080fd5b505af1158015610f71573d6000803e3d6000fd5b50505050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635b0fc9c382856040518363ffffffff1660e01b8152600401610fd29291906141f2565b600060405180830381600087803b158015610fec57600080fd5b505af1158015611000573d6000803e3d6000fd5b5050505061100e81846126d1565b50505050505050565b6000611021612516565b9050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b815260040161107e91906141d7565b60206040518083038186803b15801561109657600080fd5b505afa1580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ce919061308f565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111329061447f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf846040518263ffffffff1660e01b81526004016111ad91906141d7565b60206040518083038186803b1580156111c557600080fd5b505afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd919061308f565b73ffffffffffffffffffffffffffffffffffffffff1614611253576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124a9061435f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1661127483612527565b73ffffffffffffffffffffffffffffffffffffffff16146112ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c19061451f565b60405180910390fd5b6112d482826126d1565b5050565b60606007600085815260200190815260200160002083836040516112fd929190614056565b90815260200160405180910390208054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561139f5780601f106113745761010080835404028352916020019161139f565b820191906000526020600020905b81548152906001019060200180831161138257829003601f168201915b505050505090509392505050565b6060600560008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156114565780601f1061142b57610100808354040283529160200191611456565b820191906000526020600020905b81548152906001019060200180831161143957829003601f168201915b50505050509050919050565b600061147b82600001518360200151846040015161260c565b9050919050565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661150d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115049061449f565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16141561157c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115739061459f565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611607576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115fe9061453f565b60405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b328260405161168f929190614193565b60405180910390a150565b826116a48161242d565b6116e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116da906145df565b60405180910390fd5b8282600560008781526020019081526020016000209190611705929190612d39565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051611738929190614319565b60405180910390a250505050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000611776612516565b9050600073ffffffffffffffffffffffffffffffffffffffff1661179983612527565b73ffffffffffffffffffffffffffffffffffffffff16146117ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e6906144ff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611891576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611888906144df565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3846040518263ffffffff1660e01b815260040161190391906141d7565b60206040518083038186803b15801561191b57600080fd5b505afa15801561192f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611953919061308f565b73ffffffffffffffffffffffffffffffffffffffff16146119a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a09061455f565b60405180910390fd5b806009600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc1e082a8c26f27c26e1bf5d0ce7ddd579ec7f6d7eb3ea90d8abd6c40991bae368282604051611a2c9291906141f2565b60405180910390a15050565b82611a428161242d565b611a81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a78906145df565b60405180910390fd5b611a8c8484846126e9565b50505050565b60025481565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611b23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1a9061449f565b60405180910390fd5b611b2c816127ab565b50565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bb19061449f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c21906144bf565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611cbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb2906145ff565b60405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fdb0239c63d4033dcdd21bd44f8dd479a03efbae12f6bbe27c0a5f923d26514cc600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611d4d919061415d565b60405180910390a150565b6000806006600084815260200190815260200160002060000154600660008581526020019081526020016000206001015491509150915091565b6000611d9c612516565b9050600073ffffffffffffffffffffffffffffffffffffffff16611dbf83612527565b73ffffffffffffffffffffffffffffffffffffffff1614611e15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0c906144ff565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ead9061437f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3846040518263ffffffff1660e01b8152600401611f2891906141d7565b60206040518083038186803b158015611f4057600080fd5b505afa158015611f54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f78919061308f565b73ffffffffffffffffffffffffffffffffffffffff1614611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc59061455f565b60405180910390fd5b611fd882306126d1565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631896f70a83306040518363ffffffff1660e01b81526004016120359291906141f2565b600060405180830381600087803b15801561204f57600080fd5b505af1158015612063573d6000803e3d6000fd5b505050507fcefbe9dbadcf675eef14e23810996ff38541fc26b4dd77cd6724b0eedc96f2008260405161209691906141d7565b60405180910390a15050565b60006120f28484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612664565b90509392505050565b816121058161242d565b612144576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213b906145df565b60405180910390fd5b61214e83836126d1565b505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146121e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121da906143ff565b60405180910390fd5b6000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228c906144bf565b60405180910390fd5b83600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612320838380806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505061293a565b61232981612992565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516123589190614178565b60405180910390a150505050565b60606004600084815260200190815260200160002060008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156124205780601f106123f557610100808354040283529160200191612420565b820191906000526020600020905b81548152906001019060200180831161240357829003601f168201915b5050505050905092915050565b6000612437612516565b73ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3846040518263ffffffff1660e01b81526004016124a891906141d7565b60206040518083038186803b1580156124c057600080fd5b505afa1580156124d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f8919061308f565b73ffffffffffffffffffffffffffffffffffffffff16149050919050565b600061252260286129d6565b905090565b6000806060600460008581526020019081526020016000206000603c81526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156125e55780601f106125ba576101008083540402835291602001916125e5565b820191906000526020600020905b8154815290600101906020018083116125c857829003601f168201915b50505050509050600081511115612602576125ff81612a6b565b91505b8192505050919050565b600061265b7f621363c539a3aa1024c8837ca1dc095db03b7f9512b3a95ecb429aae7fd953ed85858560405160200161264793929190613fed565b604051602081830303815290604052612a93565b90509392505050565b60008061267a8385612ad490919063ffffffff16565b90506000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6126e582603c6126e084612b8f565b6126e9565b5050565b827f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af752838360405161271b92919061463a565b60405180910390a2603c82141561276d57827f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261275783612a6b565b6040516127649190614178565b60405180910390a25b8060046000858152602001908152602001600020600084815260200190815260200160002090805190602001906127a5929190612db9565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561281b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612812906143df565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156128a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289e9061457f565b60405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a328260405161292f929190614193565b60405180910390a150565b6000815114156129525761294d326127ab565b61298f565b60008151905060005b8181101561298c5761297f83828151811061297257fe5b60200260200101516127ab565b808060010191505061295b565b50505b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600090506129e5612bf6565b15612a5e576000836000369050039050612a5660003683906014850192612a0e93929190614711565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612ca3565b915050612a62565b3390505b80915050919050565b6000806014835114612a7c57600080fd5b600c6101000a602084015104905080915050919050565b6000612acc600254308585604051602001612ab19493929190614113565b60405160208183030381529060405280519060200120612d09565b905092915050565b60008060009050604183511415612b855760008060006020860151925060408601519150606086015160001a9050601b8160ff161015612b1557601b810190505b601b8160ff161480612b2a5750601c8160ff16145b15612b815760018782858560405160008152602001604052604051612b529493929190614297565b6020604051602081039080840390855afa158015612b74573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b606080601467ffffffffffffffff81118015612baa57600080fd5b506040519080825280601f01601f191660200182016040528015612bdd5781602001600182028036833780820191505090505b509050600c6101000a8302602082015280915050919050565b600080600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415612c9c57602c60003690501015612c97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c8e9061445f565b60405180910390fd5b600190505b8091505090565b6000806014835114612cea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ce1906145bf565b60405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b600081604051602001612d1c9190614084565b604051602081830303815290604052805190602001209050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612d7a57803560ff1916838001178555612da8565b82800160010185558215612da8579182015b82811115612da7578235825591602001919060010190612d8c565b5b509050612db59190612e39565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612dfa57805160ff1916838001178555612e28565b82800160010185558215612e28579182015b82811115612e27578251825591602001919060010190612e0c565b5b509050612e359190612e39565b5090565b5b80821115612e52576000816000905550600101612e3a565b5090565b600081359050612e65816148f9565b92915050565b600081519050612e7a816148f9565b92915050565b60008083601f840112612e9257600080fd5b8235905067ffffffffffffffff811115612eab57600080fd5b602083019150836020820283011115612ec357600080fd5b9250929050565b600081359050612ed981614910565b92915050565b600081359050612eee81614927565b92915050565b60008083601f840112612f0657600080fd5b8235905067ffffffffffffffff811115612f1f57600080fd5b602083019150836001820283011115612f3757600080fd5b9250929050565b600082601f830112612f4f57600080fd5b8135612f62612f5d82614697565b61466a565b91508082526020830160208301858383011115612f7e57600080fd5b612f89838284614861565b50505092915050565b600081359050612fa18161493e565b92915050565b60008083601f840112612fb957600080fd5b8235905067ffffffffffffffff811115612fd257600080fd5b602083019150836001820283011115612fea57600080fd5b9250929050565b60006060828403121561300357600080fd5b61300d606061466a565b9050600061301d84828501612e56565b600083015250602061303184828501612eca565b602083015250604061304584828501612eca565b60408301525092915050565b60008135905061306081614955565b92915050565b60006020828403121561307857600080fd5b600061308684828501612e56565b91505092915050565b6000602082840312156130a157600080fd5b60006130af84828501612e6b565b91505092915050565b6000602082840312156130ca57600080fd5b60006130d884828501612eca565b91505092915050565b600080604083850312156130f457600080fd5b600061310285828601612eca565b925050602061311385828601612e56565b9150509250929050565b60008060006060848603121561313257600080fd5b600061314086828701612eca565b935050602061315186828701612eca565b925050604061316286828701612eca565b9150509250925092565b6000806000806060858703121561318257600080fd5b600061319087828801612eca565b94505060206131a187828801612eca565b935050604085013567ffffffffffffffff8111156131be57600080fd5b6131ca87828801612ef4565b925092505092959194509250565b6000806000604084860312156131ed57600080fd5b60006131fb86828701612eca565b935050602084013567ffffffffffffffff81111561321857600080fd5b61322486828701612ef4565b92509250509250925092565b60008060006040848603121561324557600080fd5b600061325386828701612eca565b935050602084013567ffffffffffffffff81111561327057600080fd5b61327c86828701612fa7565b92509250509250925092565b6000806000806000606086880312156132a057600080fd5b60006132ae88828901612eca565b955050602086013567ffffffffffffffff8111156132cb57600080fd5b6132d788828901612fa7565b9450945050604086013567ffffffffffffffff8111156132f657600080fd5b61330288828901612fa7565b92509250509295509295909350565b6000806040838503121561332457600080fd5b600061333285828601612eca565b925050602061334385828601613051565b9150509250929050565b60008060006060848603121561336257600080fd5b600061337086828701612eca565b935050602061338186828701613051565b925050604084013567ffffffffffffffff81111561339e57600080fd5b6133aa86828701612f3e565b9150509250925092565b6000602082840312156133c657600080fd5b60006133d484828501612edf565b91505092915050565b6000602082840312156133ef57600080fd5b60006133fd84828501612f92565b91505092915050565b6000806000806060858703121561341c57600080fd5b600061342a87828801612f92565b945050602085013567ffffffffffffffff81111561344757600080fd5b61345387828801612e80565b9350935050604061346687828801612e56565b91505092959194509250565b60006060828403121561348457600080fd5b600061349284828501612ff1565b91505092915050565b6134a4816147f5565b82525050565b6134b381614744565b82525050565b6134ca6134c582614744565b6148a3565b82525050565b6134d981614756565b82525050565b6134e881614762565b82525050565b6134ff6134fa82614762565b6148b5565b82525050565b6000613510826146c3565b61351a81856146d9565b935061352a818560208601614870565b613533816148db565b840191505092915050565b6000613549826146c3565b61355381856146ea565b9350613563818560208601614870565b80840191505092915050565b61357881614807565b82525050565b6135878161482b565b82525050565b600061359983856146f5565b93506135a6838584614861565b6135af836148db565b840190509392505050565b60006135c68385614706565b93506135d3838584614861565b82840190509392505050565b60006135ea826146ce565b6135f481856146f5565b9350613604818560208601614870565b61360d816148db565b840191505092915050565b6000613625601983614706565b91507f737570706f727473496e746572666163652862797465733429000000000000006000830152601982019050919050565b60006136656024836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c6964206e6f6465207265736f60008301527f6c766572000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006136cb6021836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c6964206e6f6465206f776e6560008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137316029836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c696420677561726469616e2060008301527f7369676e617475726500000000000000000000000000000000000000000000006020830152604082019050919050565b60006137976022836146f5565b91507f454e53436f6e74726f6c6c65723a206c6162656c20616c72656164792074616b60008301527f656e0000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137fd601c83614706565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b600061383d6020836146f5565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b600061387d602f836146f5565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006138e3600d83614706565b91507f61646472286279746573333229000000000000000000000000000000000000006000830152600d82019050919050565b6000613923601b836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c6964206e6f646500000000006000830152602082019050919050565b60006139636021836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520646f65736e2774206578697360008301527f74000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006139c96022836146f5565b91507f47617465776179526563697069656e743a20696e76616c6964206d73672e646160008301527f74610000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a2f601483614706565b91507f7465787428627974657333322c737472696e67290000000000000000000000006000830152601482019050919050565b6000613a6f600d83614706565b91507f6e616d65286279746573333229000000000000000000000000000000000000006000830152600d82019050919050565b6000613aaf602b836146f5565b91507f454e53436f6e74726f6c6c65723a2063616c6c6572206973206e6f742074686560008301527f206e6f6465206f776e65720000000000000000000000000000000000000000006020830152604082019050919050565b6000613b156026836146f5565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613b7b6026836146f5565b91507f454e53436f6e74726f6c6c65723a2063616e6e6f74207365742030783020726560008301527f67697374727900000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613be16025836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520616c7265616479207375626d60008301527f69747465640000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c47600f83614706565b91507f7075626b657928627974657333322900000000000000000000000000000000006000830152600f82019050919050565b6000613c876022836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520616c7265616479206578697360008301527f74730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613ced6023836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520616c726561647920696e207360008301527f796e6300000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d53601f836146f5565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000613d936025836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c696420656e73206e6f64652060008301527f6f776e65720000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df96020836146f5565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b6000613e39601b836146f5565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b6000613e79601d836146f5565b91507f42797465734c69623a20696e76616c69642064617461206c656e6774680000006000830152602082019050919050565b6000613eb96037836146f5565b91507f454e5341627374726163745265736f6c7665723a20726576657274656420627960008301527f206f6e6c794e6f64654f776e6572206d6f6469666965720000000000000000006020830152604082019050919050565b6000613f1f601283614706565b91507f6164647228627974657333322c75696e742900000000000000000000000000006000830152601282019050919050565b6000613f5f6023836146f5565b91507f454e53436f6e74726f6c6c65723a20726567697374727920616c72656164792060008301527f73657400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b613fc1816147ca565b82525050565b613fd8613fd3826147ca565b6148d1565b82525050565b613fe7816147e8565b82525050565b6000613ff982866134b9565b60148201915061400982856134ee565b60208201915061401982846134ee565b602082019150819050949350505050565b600061403682856134ee565b60208201915061404682846134ee565b6020820191508190509392505050565b60006140638284866135ba565b91508190509392505050565b600061407a82613618565b9150819050919050565b600061408f826137f0565b915061409b82846134ee565b60208201915081905092915050565b60006140b5826138d6565b9150819050919050565b60006140ca82613a22565b9150819050919050565b60006140df82613a62565b9150819050919050565b60006140f482613c3a565b9150819050919050565b600061410982613f12565b9150819050919050565b600061411f8287613fc7565b60208201915061412f82866134b9565b60148201915061413f82856134ee565b60208201915061414f828461353e565b915081905095945050505050565b600060208201905061417260008301846134aa565b92915050565b600060208201905061418d600083018461349b565b92915050565b60006040820190506141a8600083018561349b565b6141b560208301846134aa565b9392505050565b60006020820190506141d160008301846134d0565b92915050565b60006020820190506141ec60008301846134df565b92915050565b600060408201905061420760008301856134df565b61421460208301846134aa565b9392505050565b600060408201905061423060008301856134df565b61423d60208301846134df565b9392505050565b600060a08201905061425960008301886134df565b61426660208301876134df565b61427360408301866134aa565b61428060608301856134aa565b61428d608083018461357e565b9695505050505050565b60006080820190506142ac60008301876134df565b6142b96020830186613fde565b6142c660408301856134df565b6142d360608301846134df565b95945050505050565b600060208201905081810360008301526142f68184613505565b905092915050565b6000602082019050614313600083018461356f565b92915050565b6000602082019050818103600083015261433481848661358d565b90509392505050565b6000602082019050818103600083015261435781846135df565b905092915050565b6000602082019050818103600083015261437881613658565b9050919050565b60006020820190508181036000830152614398816136be565b9050919050565b600060208201905081810360008301526143b881613724565b9050919050565b600060208201905081810360008301526143d88161378a565b9050919050565b600060208201905081810360008301526143f881613830565b9050919050565b6000602082019050818103600083015261441881613870565b9050919050565b6000602082019050818103600083015261443881613916565b9050919050565b6000602082019050818103600083015261445881613956565b9050919050565b60006020820190508181036000830152614478816139bc565b9050919050565b6000602082019050818103600083015261449881613aa2565b9050919050565b600060208201905081810360008301526144b881613b08565b9050919050565b600060208201905081810360008301526144d881613b6e565b9050919050565b600060208201905081810360008301526144f881613bd4565b9050919050565b6000602082019050818103600083015261451881613c7a565b9050919050565b6000602082019050818103600083015261453881613ce0565b9050919050565b6000602082019050818103600083015261455881613d46565b9050919050565b6000602082019050818103600083015261457881613d86565b9050919050565b6000602082019050818103600083015261459881613dec565b9050919050565b600060208201905081810360008301526145b881613e2c565b9050919050565b600060208201905081810360008301526145d881613e6c565b9050919050565b600060208201905081810360008301526145f881613eac565b9050919050565b6000602082019050818103600083015261461881613f52565b9050919050565b60006020820190506146346000830184613fb8565b92915050565b600060408201905061464f6000830185613fb8565b81810360208301526146618184613505565b90509392505050565b6000604051905081810181811067ffffffffffffffff8211171561468d57600080fd5b8060405250919050565b600067ffffffffffffffff8211156146ae57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000808585111561472157600080fd5b8386111561472e57600080fd5b6001850283019150848603905094509492505050565b600061474f826147aa565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60006147a382614744565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600067ffffffffffffffff82169050919050565b600060ff82169050919050565b60006148008261483d565b9050919050565b600061481282614819565b9050919050565b6000614824826147aa565b9050919050565b6000614836826147d4565b9050919050565b60006148488261484f565b9050919050565b600061485a826147aa565b9050919050565b82818337600083830152505050565b60005b8381101561488e578082015181840152602081019050614873565b8381111561489d576000848401525b50505050565b60006148ae826148bf565b9050919050565b6000819050919050565b60006148ca826148ec565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61490281614744565b811461490d57600080fd5b50565b61491981614762565b811461492457600080fd5b50565b6149308161476c565b811461493b57600080fd5b50565b61494781614798565b811461495257600080fd5b50565b61495e816147ca565b811461496957600080fd5b5056fea164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101c45760003560e01c806371404156116100f9578063a91ee0dc11610097578063d0f710d611610071578063d0f710d614610512578063d5fa2b0014610542578063dc5b68a61461055e578063f1cb7e061461057a576101c4565b8063a91ee0dc146104a9578063c8690233146104c5578063c8cc2aee146104f6576101c4565b80637d0e0e7e116100d35780637d0e0e7e146104375780638b95dd71146104535780639a8a05921461046f578063a526d83b1461048d576101c4565b806371404156146103e157806377372213146103fd5780637b10399914610419576101c4565b8063392e53cd1161016657806355800f871161014057806355800f871461033557806359d1d43c14610351578063691f3431146103815780636df0cf42146103b1576101c4565b8063392e53cd146102cb5780633b3b57de146102e957806346386f7314610319576101c4565b8063116191b6116101a2578063116191b6146102455780631b3cd1421461026357806329ae6a7e1461029357806329cd62ea146102af576101c4565b806301ffc9a7146101c95780630c68ba21146101f957806310f13a8c14610229575b600080fd5b6101e360048036038101906101de91906133b4565b6105aa565b6040516101f091906141bc565b60405180910390f35b610213600480360381019061020e9190613066565b610834565b60405161022091906141bc565b60405180910390f35b610243600480360381019061023e9190613288565b610889565b005b61024d61096d565b60405161025a919061415d565b60405180910390f35b61027d600480360381019061027891906130b8565b610993565b60405161028a919061415d565b60405180910390f35b6102ad60048036038101906102a891906130b8565b6109c6565b005b6102c960048036038101906102c4919061311d565b610beb565b005b6102d3610cb3565b6040516102e091906141bc565b60405180910390f35b61030360048036038101906102fe91906130b8565b610d0b565b604051610310919061415d565b60405180910390f35b610333600480360381019061032e919061316c565b610d1d565b005b61034f600480360381019061034a91906130b8565b611017565b005b61036b60048036038101906103669190613230565b6112d8565b604051610378919061433d565b60405180910390f35b61039b600480360381019061039691906130b8565b6113ad565b6040516103a8919061433d565b60405180910390f35b6103cb60048036038101906103c69190613472565b611462565b6040516103d891906141d7565b60405180910390f35b6103fb60048036038101906103f69190613066565b611482565b005b61041760048036038101906104129190613230565b61169a565b005b610421611746565b60405161042e91906142fe565b60405180910390f35b610451600480360381019061044c91906130b8565b61176c565b005b61046d6004803603810190610468919061334d565b611a38565b005b610477611a92565b604051610484919061461f565b60405180910390f35b6104a760048036038101906104a29190613066565b611a98565b005b6104c360048036038101906104be91906133dd565b611b2f565b005b6104df60048036038101906104da91906130b8565b611d58565b6040516104ed92919061421b565b60405180910390f35b610510600480360381019061050b91906130b8565b611d92565b005b61052c600480360381019061052791906131d8565b6120a2565b60405161053991906141bc565b60405180910390f35b61055c600480360381019061055791906130e1565b6120fb565b005b61057860048036038101906105739190613406565b612153565b005b610594600480360381019061058f9190613311565b612366565b6040516105a191906142dc565b60405180910390f35b60006040516020016105bb9061406f565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061067d5750604051602001610626906140aa565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806106e95750604051602001610692906140fe565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061075557506040516020016106fe906140d4565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107c1575060405160200161076a906140e9565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061082d57506040516020016107d6906140bf565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b846108938161242d565b6108d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c9906145df565b60405180910390fd5b82826007600089815260200190815260200160002087876040516108f7929190614056565b90815260200160405180910390209190610912929190612d39565b508484604051610923929190614056565b6040518091039020867fd8c9334b1a9c2f9da342a0a2b32629c1a229b6445dad78947f674b44444a7550878760405161095d929190614319565b60405180910390a3505050505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60096020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006109d0612516565b90503073ffffffffffffffffffffffffffffffffffffffff166109f283612527565b73ffffffffffffffffffffffffffffffffffffffff1614610a48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3f9061443f565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ae9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae09061437f565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635b0fc9c383836040518363ffffffff1660e01b8152600401610b469291906141f2565b600060405180830381600087803b158015610b6057600080fd5b505af1158015610b74573d6000803e3d6000fd5b505050506009600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690557f7803a16d95f9ca635bdec561006625e7444d8a9f8463866643cc03af011779d38282604051610bdf9291906141f2565b60405180910390a15050565b82610bf58161242d565b610c34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2b906145df565b60405180910390fd5b604051806040016040528084815260200183815250600660008681526020019081526020016000206000820151816000015560208201518160010155905050837f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e468484604051610ca592919061421b565b60405180910390a250505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b6000610d1682612527565b9050919050565b6000610d27612516565b90506000610d3682878761260c565b9050610d868185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612664565b610dc5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbc9061439f565b60405180910390fd5b60008686604051602001610dda92919061402a565b6040516020818303038152906040528051906020012090503073ffffffffffffffffffffffffffffffffffffffff16610e1288612527565b73ffffffffffffffffffffffffffffffffffffffff1614610e68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5f9061441f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16610e8982612527565b73ffffffffffffffffffffffffffffffffffffffff1614610edf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed6906143bf565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635ef2c7f08888303060006040518663ffffffff1660e01b8152600401610f43959493929190614244565b600060405180830381600087803b158015610f5d57600080fd5b505af1158015610f71573d6000803e3d6000fd5b50505050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635b0fc9c382856040518363ffffffff1660e01b8152600401610fd29291906141f2565b600060405180830381600087803b158015610fec57600080fd5b505af1158015611000573d6000803e3d6000fd5b5050505061100e81846126d1565b50505050505050565b6000611021612516565b9050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b815260040161107e91906141d7565b60206040518083038186803b15801561109657600080fd5b505afa1580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ce919061308f565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111329061447f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf846040518263ffffffff1660e01b81526004016111ad91906141d7565b60206040518083038186803b1580156111c557600080fd5b505afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd919061308f565b73ffffffffffffffffffffffffffffffffffffffff1614611253576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124a9061435f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1661127483612527565b73ffffffffffffffffffffffffffffffffffffffff16146112ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c19061451f565b60405180910390fd5b6112d482826126d1565b5050565b60606007600085815260200190815260200160002083836040516112fd929190614056565b90815260200160405180910390208054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561139f5780601f106113745761010080835404028352916020019161139f565b820191906000526020600020905b81548152906001019060200180831161138257829003601f168201915b505050505090509392505050565b6060600560008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156114565780601f1061142b57610100808354040283529160200191611456565b820191906000526020600020905b81548152906001019060200180831161143957829003601f168201915b50505050509050919050565b600061147b82600001518360200151846040015161260c565b9050919050565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661150d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115049061449f565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16141561157c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115739061459f565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611607576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115fe9061453f565b60405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b328260405161168f929190614193565b60405180910390a150565b826116a48161242d565b6116e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116da906145df565b60405180910390fd5b8282600560008781526020019081526020016000209190611705929190612d39565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051611738929190614319565b60405180910390a250505050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000611776612516565b9050600073ffffffffffffffffffffffffffffffffffffffff1661179983612527565b73ffffffffffffffffffffffffffffffffffffffff16146117ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e6906144ff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611891576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611888906144df565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3846040518263ffffffff1660e01b815260040161190391906141d7565b60206040518083038186803b15801561191b57600080fd5b505afa15801561192f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611953919061308f565b73ffffffffffffffffffffffffffffffffffffffff16146119a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a09061455f565b60405180910390fd5b806009600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc1e082a8c26f27c26e1bf5d0ce7ddd579ec7f6d7eb3ea90d8abd6c40991bae368282604051611a2c9291906141f2565b60405180910390a15050565b82611a428161242d565b611a81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a78906145df565b60405180910390fd5b611a8c8484846126e9565b50505050565b60025481565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611b23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1a9061449f565b60405180910390fd5b611b2c816127ab565b50565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bb19061449f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c21906144bf565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611cbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb2906145ff565b60405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fdb0239c63d4033dcdd21bd44f8dd479a03efbae12f6bbe27c0a5f923d26514cc600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611d4d919061415d565b60405180910390a150565b6000806006600084815260200190815260200160002060000154600660008581526020019081526020016000206001015491509150915091565b6000611d9c612516565b9050600073ffffffffffffffffffffffffffffffffffffffff16611dbf83612527565b73ffffffffffffffffffffffffffffffffffffffff1614611e15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0c906144ff565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166009600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ead9061437f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3846040518263ffffffff1660e01b8152600401611f2891906141d7565b60206040518083038186803b158015611f4057600080fd5b505afa158015611f54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f78919061308f565b73ffffffffffffffffffffffffffffffffffffffff1614611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc59061455f565b60405180910390fd5b611fd882306126d1565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631896f70a83306040518363ffffffff1660e01b81526004016120359291906141f2565b600060405180830381600087803b15801561204f57600080fd5b505af1158015612063573d6000803e3d6000fd5b505050507fcefbe9dbadcf675eef14e23810996ff38541fc26b4dd77cd6724b0eedc96f2008260405161209691906141d7565b60405180910390a15050565b60006120f28484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612664565b90509392505050565b816121058161242d565b612144576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213b906145df565b60405180910390fd5b61214e83836126d1565b505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146121e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121da906143ff565b60405180910390fd5b6000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228c906144bf565b60405180910390fd5b83600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612320838380806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505061293a565b61232981612992565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516123589190614178565b60405180910390a150505050565b60606004600084815260200190815260200160002060008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156124205780601f106123f557610100808354040283529160200191612420565b820191906000526020600020905b81548152906001019060200180831161240357829003601f168201915b5050505050905092915050565b6000612437612516565b73ffffffffffffffffffffffffffffffffffffffff16600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3846040518263ffffffff1660e01b81526004016124a891906141d7565b60206040518083038186803b1580156124c057600080fd5b505afa1580156124d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f8919061308f565b73ffffffffffffffffffffffffffffffffffffffff16149050919050565b600061252260286129d6565b905090565b6000806060600460008581526020019081526020016000206000603c81526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156125e55780601f106125ba576101008083540402835291602001916125e5565b820191906000526020600020905b8154815290600101906020018083116125c857829003601f168201915b50505050509050600081511115612602576125ff81612a6b565b91505b8192505050919050565b600061265b7f621363c539a3aa1024c8837ca1dc095db03b7f9512b3a95ecb429aae7fd953ed85858560405160200161264793929190613fed565b604051602081830303815290604052612a93565b90509392505050565b60008061267a8385612ad490919063ffffffff16565b90506000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6126e582603c6126e084612b8f565b6126e9565b5050565b827f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af752838360405161271b92919061463a565b60405180910390a2603c82141561276d57827f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261275783612a6b565b6040516127649190614178565b60405180910390a25b8060046000858152602001908152602001600020600084815260200190815260200160002090805190602001906127a5929190612db9565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561281b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612812906143df565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156128a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289e9061457f565b60405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a328260405161292f929190614193565b60405180910390a150565b6000815114156129525761294d326127ab565b61298f565b60008151905060005b8181101561298c5761297f83828151811061297257fe5b60200260200101516127ab565b808060010191505061295b565b50505b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600090506129e5612bf6565b15612a5e576000836000369050039050612a5660003683906014850192612a0e93929190614711565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612ca3565b915050612a62565b3390505b80915050919050565b6000806014835114612a7c57600080fd5b600c6101000a602084015104905080915050919050565b6000612acc600254308585604051602001612ab19493929190614113565b60405160208183030381529060405280519060200120612d09565b905092915050565b60008060009050604183511415612b855760008060006020860151925060408601519150606086015160001a9050601b8160ff161015612b1557601b810190505b601b8160ff161480612b2a5750601c8160ff16145b15612b815760018782858560405160008152602001604052604051612b529493929190614297565b6020604051602081039080840390855afa158015612b74573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b606080601467ffffffffffffffff81118015612baa57600080fd5b506040519080825280601f01601f191660200182016040528015612bdd5781602001600182028036833780820191505090505b509050600c6101000a8302602082015280915050919050565b600080600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415612c9c57602c60003690501015612c97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c8e9061445f565b60405180910390fd5b600190505b8091505090565b6000806014835114612cea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ce1906145bf565b60405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b600081604051602001612d1c9190614084565b604051602081830303815290604052805190602001209050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612d7a57803560ff1916838001178555612da8565b82800160010185558215612da8579182015b82811115612da7578235825591602001919060010190612d8c565b5b509050612db59190612e39565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612dfa57805160ff1916838001178555612e28565b82800160010185558215612e28579182015b82811115612e27578251825591602001919060010190612e0c565b5b509050612e359190612e39565b5090565b5b80821115612e52576000816000905550600101612e3a565b5090565b600081359050612e65816148f9565b92915050565b600081519050612e7a816148f9565b92915050565b60008083601f840112612e9257600080fd5b8235905067ffffffffffffffff811115612eab57600080fd5b602083019150836020820283011115612ec357600080fd5b9250929050565b600081359050612ed981614910565b92915050565b600081359050612eee81614927565b92915050565b60008083601f840112612f0657600080fd5b8235905067ffffffffffffffff811115612f1f57600080fd5b602083019150836001820283011115612f3757600080fd5b9250929050565b600082601f830112612f4f57600080fd5b8135612f62612f5d82614697565b61466a565b91508082526020830160208301858383011115612f7e57600080fd5b612f89838284614861565b50505092915050565b600081359050612fa18161493e565b92915050565b60008083601f840112612fb957600080fd5b8235905067ffffffffffffffff811115612fd257600080fd5b602083019150836001820283011115612fea57600080fd5b9250929050565b60006060828403121561300357600080fd5b61300d606061466a565b9050600061301d84828501612e56565b600083015250602061303184828501612eca565b602083015250604061304584828501612eca565b60408301525092915050565b60008135905061306081614955565b92915050565b60006020828403121561307857600080fd5b600061308684828501612e56565b91505092915050565b6000602082840312156130a157600080fd5b60006130af84828501612e6b565b91505092915050565b6000602082840312156130ca57600080fd5b60006130d884828501612eca565b91505092915050565b600080604083850312156130f457600080fd5b600061310285828601612eca565b925050602061311385828601612e56565b9150509250929050565b60008060006060848603121561313257600080fd5b600061314086828701612eca565b935050602061315186828701612eca565b925050604061316286828701612eca565b9150509250925092565b6000806000806060858703121561318257600080fd5b600061319087828801612eca565b94505060206131a187828801612eca565b935050604085013567ffffffffffffffff8111156131be57600080fd5b6131ca87828801612ef4565b925092505092959194509250565b6000806000604084860312156131ed57600080fd5b60006131fb86828701612eca565b935050602084013567ffffffffffffffff81111561321857600080fd5b61322486828701612ef4565b92509250509250925092565b60008060006040848603121561324557600080fd5b600061325386828701612eca565b935050602084013567ffffffffffffffff81111561327057600080fd5b61327c86828701612fa7565b92509250509250925092565b6000806000806000606086880312156132a057600080fd5b60006132ae88828901612eca565b955050602086013567ffffffffffffffff8111156132cb57600080fd5b6132d788828901612fa7565b9450945050604086013567ffffffffffffffff8111156132f657600080fd5b61330288828901612fa7565b92509250509295509295909350565b6000806040838503121561332457600080fd5b600061333285828601612eca565b925050602061334385828601613051565b9150509250929050565b60008060006060848603121561336257600080fd5b600061337086828701612eca565b935050602061338186828701613051565b925050604084013567ffffffffffffffff81111561339e57600080fd5b6133aa86828701612f3e565b9150509250925092565b6000602082840312156133c657600080fd5b60006133d484828501612edf565b91505092915050565b6000602082840312156133ef57600080fd5b60006133fd84828501612f92565b91505092915050565b6000806000806060858703121561341c57600080fd5b600061342a87828801612f92565b945050602085013567ffffffffffffffff81111561344757600080fd5b61345387828801612e80565b9350935050604061346687828801612e56565b91505092959194509250565b60006060828403121561348457600080fd5b600061349284828501612ff1565b91505092915050565b6134a4816147f5565b82525050565b6134b381614744565b82525050565b6134ca6134c582614744565b6148a3565b82525050565b6134d981614756565b82525050565b6134e881614762565b82525050565b6134ff6134fa82614762565b6148b5565b82525050565b6000613510826146c3565b61351a81856146d9565b935061352a818560208601614870565b613533816148db565b840191505092915050565b6000613549826146c3565b61355381856146ea565b9350613563818560208601614870565b80840191505092915050565b61357881614807565b82525050565b6135878161482b565b82525050565b600061359983856146f5565b93506135a6838584614861565b6135af836148db565b840190509392505050565b60006135c68385614706565b93506135d3838584614861565b82840190509392505050565b60006135ea826146ce565b6135f481856146f5565b9350613604818560208601614870565b61360d816148db565b840191505092915050565b6000613625601983614706565b91507f737570706f727473496e746572666163652862797465733429000000000000006000830152601982019050919050565b60006136656024836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c6964206e6f6465207265736f60008301527f6c766572000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006136cb6021836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c6964206e6f6465206f776e6560008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137316029836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c696420677561726469616e2060008301527f7369676e617475726500000000000000000000000000000000000000000000006020830152604082019050919050565b60006137976022836146f5565b91507f454e53436f6e74726f6c6c65723a206c6162656c20616c72656164792074616b60008301527f656e0000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137fd601c83614706565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b600061383d6020836146f5565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b600061387d602f836146f5565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006138e3600d83614706565b91507f61646472286279746573333229000000000000000000000000000000000000006000830152600d82019050919050565b6000613923601b836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c6964206e6f646500000000006000830152602082019050919050565b60006139636021836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520646f65736e2774206578697360008301527f74000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006139c96022836146f5565b91507f47617465776179526563697069656e743a20696e76616c6964206d73672e646160008301527f74610000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a2f601483614706565b91507f7465787428627974657333322c737472696e67290000000000000000000000006000830152601482019050919050565b6000613a6f600d83614706565b91507f6e616d65286279746573333229000000000000000000000000000000000000006000830152600d82019050919050565b6000613aaf602b836146f5565b91507f454e53436f6e74726f6c6c65723a2063616c6c6572206973206e6f742074686560008301527f206e6f6465206f776e65720000000000000000000000000000000000000000006020830152604082019050919050565b6000613b156026836146f5565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613b7b6026836146f5565b91507f454e53436f6e74726f6c6c65723a2063616e6e6f74207365742030783020726560008301527f67697374727900000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613be16025836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520616c7265616479207375626d60008301527f69747465640000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c47600f83614706565b91507f7075626b657928627974657333322900000000000000000000000000000000006000830152600f82019050919050565b6000613c876022836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520616c7265616479206578697360008301527f74730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613ced6023836146f5565b91507f454e53436f6e74726f6c6c65723a206e6f646520616c726561647920696e207360008301527f796e6300000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d53601f836146f5565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000613d936025836146f5565b91507f454e53436f6e74726f6c6c65723a20696e76616c696420656e73206e6f64652060008301527f6f776e65720000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df96020836146f5565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b6000613e39601b836146f5565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b6000613e79601d836146f5565b91507f42797465734c69623a20696e76616c69642064617461206c656e6774680000006000830152602082019050919050565b6000613eb96037836146f5565b91507f454e5341627374726163745265736f6c7665723a20726576657274656420627960008301527f206f6e6c794e6f64654f776e6572206d6f6469666965720000000000000000006020830152604082019050919050565b6000613f1f601283614706565b91507f6164647228627974657333322c75696e742900000000000000000000000000006000830152601282019050919050565b6000613f5f6023836146f5565b91507f454e53436f6e74726f6c6c65723a20726567697374727920616c72656164792060008301527f73657400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b613fc1816147ca565b82525050565b613fd8613fd3826147ca565b6148d1565b82525050565b613fe7816147e8565b82525050565b6000613ff982866134b9565b60148201915061400982856134ee565b60208201915061401982846134ee565b602082019150819050949350505050565b600061403682856134ee565b60208201915061404682846134ee565b6020820191508190509392505050565b60006140638284866135ba565b91508190509392505050565b600061407a82613618565b9150819050919050565b600061408f826137f0565b915061409b82846134ee565b60208201915081905092915050565b60006140b5826138d6565b9150819050919050565b60006140ca82613a22565b9150819050919050565b60006140df82613a62565b9150819050919050565b60006140f482613c3a565b9150819050919050565b600061410982613f12565b9150819050919050565b600061411f8287613fc7565b60208201915061412f82866134b9565b60148201915061413f82856134ee565b60208201915061414f828461353e565b915081905095945050505050565b600060208201905061417260008301846134aa565b92915050565b600060208201905061418d600083018461349b565b92915050565b60006040820190506141a8600083018561349b565b6141b560208301846134aa565b9392505050565b60006020820190506141d160008301846134d0565b92915050565b60006020820190506141ec60008301846134df565b92915050565b600060408201905061420760008301856134df565b61421460208301846134aa565b9392505050565b600060408201905061423060008301856134df565b61423d60208301846134df565b9392505050565b600060a08201905061425960008301886134df565b61426660208301876134df565b61427360408301866134aa565b61428060608301856134aa565b61428d608083018461357e565b9695505050505050565b60006080820190506142ac60008301876134df565b6142b96020830186613fde565b6142c660408301856134df565b6142d360608301846134df565b95945050505050565b600060208201905081810360008301526142f68184613505565b905092915050565b6000602082019050614313600083018461356f565b92915050565b6000602082019050818103600083015261433481848661358d565b90509392505050565b6000602082019050818103600083015261435781846135df565b905092915050565b6000602082019050818103600083015261437881613658565b9050919050565b60006020820190508181036000830152614398816136be565b9050919050565b600060208201905081810360008301526143b881613724565b9050919050565b600060208201905081810360008301526143d88161378a565b9050919050565b600060208201905081810360008301526143f881613830565b9050919050565b6000602082019050818103600083015261441881613870565b9050919050565b6000602082019050818103600083015261443881613916565b9050919050565b6000602082019050818103600083015261445881613956565b9050919050565b60006020820190508181036000830152614478816139bc565b9050919050565b6000602082019050818103600083015261449881613aa2565b9050919050565b600060208201905081810360008301526144b881613b08565b9050919050565b600060208201905081810360008301526144d881613b6e565b9050919050565b600060208201905081810360008301526144f881613bd4565b9050919050565b6000602082019050818103600083015261451881613c7a565b9050919050565b6000602082019050818103600083015261453881613ce0565b9050919050565b6000602082019050818103600083015261455881613d46565b9050919050565b6000602082019050818103600083015261457881613d86565b9050919050565b6000602082019050818103600083015261459881613dec565b9050919050565b600060208201905081810360008301526145b881613e2c565b9050919050565b600060208201905081810360008301526145d881613e6c565b9050919050565b600060208201905081810360008301526145f881613eac565b9050919050565b6000602082019050818103600083015261461881613f52565b9050919050565b60006020820190506146346000830184613fb8565b92915050565b600060408201905061464f6000830185613fb8565b81810360208301526146618184613505565b90509392505050565b6000604051905081810181811067ffffffffffffffff8211171561468d57600080fd5b8060405250919050565b600067ffffffffffffffff8211156146ae57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000808585111561472157600080fd5b8386111561472e57600080fd5b6001850283019150848603905094509492505050565b600061474f826147aa565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60006147a382614744565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600067ffffffffffffffff82169050919050565b600060ff82169050919050565b60006148008261483d565b9050919050565b600061481282614819565b9050919050565b6000614824826147aa565b9050919050565b6000614836826147d4565b9050919050565b60006148488261484f565b9050919050565b600061485a826147aa565b9050919050565b82818337600083830152505050565b60005b8381101561488e578082015181840152602081019050614873565b8381111561489d576000848401525b50505050565b60006148ae826148bf565b9050919050565b6000819050919050565b60006148ca826148ec565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61490281614744565b811461490d57600080fd5b50565b61491981614762565b811461492457600080fd5b50565b6149308161476c565b811461493b57600080fd5b50565b61494781614798565b811461495257600080fd5b50565b61495e816147ca565b811461496957600080fd5b5056fea164736f6c634300060c000a", diff --git a/deployments/neonDevnet/ENSHelper.json b/deployments/neonDevnet/ENSHelper.json index f048f30d..9f683c0a 100644 --- a/deployments/neonDevnet/ENSHelper.json +++ b/deployments/neonDevnet/ENSHelper.json @@ -97,7 +97,7 @@ "type": "function" } ], - "transactionHash": "0x537758f8c59f5f98525af01cac5f20a29ccab5bdf76a04e327222c9c94c099bb", + "transactionHash": "0x9ccb74f863097ed19ced9d6999366ee01a5bcc8215ff5fade4e670db0c72f823", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -105,16 +105,16 @@ "transactionIndex": 0, "gasUsed": "44643600", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2704290371908a4c061c3fe59d002f04a555310cd7bb5c28de6a2b8fd262cc0b", - "transactionHash": "0x537758f8c59f5f98525af01cac5f20a29ccab5bdf76a04e327222c9c94c099bb", + "blockHash": "0xb2ba894f3d6edc9029aff5d6b9e0fd4e00d3c9f399ec46d987f74d8de0c6f97f", + "transactionHash": "0x9ccb74f863097ed19ced9d6999366ee01a5bcc8215ff5fade4e670db0c72f823", "logs": [], - "blockNumber": 173996784, + "blockNumber": 178555064, "cumulativeGasUsed": "44643600", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "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\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"}],\"name\":\"getAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"}],\"name\":\"getNames\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ENSRegistry\",\"name\":\"registry_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"contract ENSRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"},\"getAddresses(bytes32[])\":{\"params\":{\"nodes\":\"array of nodes\"},\"returns\":{\"_0\":\"nodes addresses\"}},\"getNames(bytes32[])\":{\"params\":{\"nodes\":\"array of nodes\"},\"returns\":{\"_0\":\"nodes names\"}},\"initialize(address)\":{\"params\":{\"registry_\":\"ENS registry address\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}}},\"title\":\"ENS helper\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAddresses(bytes32[])\":{\"notice\":\"Gets nodes addresses\"},\"getNames(bytes32[])\":{\"notice\":\"Gets nodes names\"},\"initialize(address)\":{\"notice\":\"Initializes `ENSLookupHelper` contract\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ens/ENSHelper.sol\":\"ENSHelper\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"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/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\\u0142aw G\\u0142ogowski \\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\",\"keccak256\":\"0x38b9f6686c97eef1da7a015817b47f335fec507c30d4f22101d850908805e43f\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xe00dbdea09d17d41c2c14266e6e1b6b95938c0d374b266bb44a91cfcf0495612\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xc67d8bdd4904684e5d3388f7ca7d18c7d407058d6b548d8c591404c758a1ac60\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xd2f0c5ed5f5058755512c0916496da6bcf4cf18a0026ee8d20b4306656ce5142\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x1d2d4b21f59225fbefe0e5aaff87aff8f11afe5281745934d595e15770557ead\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610e74806100606000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806338bc01b51461005c578063392e53cd1461008c5780637b103999146100aa578063c4d66de8146100c8578063dc6008e2146100e4575b600080fd5b610076600480360381019061007191906108a6565b610114565b6040516100839190610b55565b60405180910390f35b6100946101ec565b6040516100a19190610b99565b60405180910390f35b6100b2610242565b6040516100bf9190610bcf565b60405180910390f35b6100e260048036038101906100dd91906108e7565b610268565b005b6100fe60048036038101906100f991906108a6565b6103b2565b60405161010b9190610b77565b60405180910390f35b606060008251905060608167ffffffffffffffff8111801561013557600080fd5b506040519080825280602002602001820160405280156101645781602001602082028036833780820191505090505b50905060005b828110156101e15761018e85828151811061018157fe5b6020026020010151610460565b82828151811061019a57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808060010191505061016a565b508092505050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146102f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ed90610bea565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516103a79190610b3a565b60405180910390a150565b606060008251905060608167ffffffffffffffff811180156103d357600080fd5b5060405190808252806020026020018201604052801561040757816020015b60608152602001906001900390816103f25790505b50905060005b828110156104555761043185828151811061042457fe5b60200260200101516105e1565b82828151811061043d57fe5b6020026020010181905250808060010191505061040d565b508092505050919050565b6000806000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf856040518263ffffffff1660e01b81526004016104c09190610bb4565b60206040518083038186803b1580156104d857600080fd5b505afa1580156104ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610510919061087d565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146105d7578073ffffffffffffffffffffffffffffffffffffffff16633b3b57de856040518263ffffffff1660e01b815260040161057f9190610bb4565b60206040518083038186803b15801561059757600080fd5b505afa9250505080156105c857506040513d601f19601f820116820180604052508101906105c5919061087d565b60015b6105d1576105d6565b809250505b5b8192505050919050565b6060806000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf856040518263ffffffff1660e01b81526004016106419190610bb4565b60206040518083038186803b15801561065957600080fd5b505afa15801561066d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610691919061087d565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461075d578073ffffffffffffffffffffffffffffffffffffffff1663691f3431856040518263ffffffff1660e01b81526004016107009190610bb4565b60006040518083038186803b15801561071857600080fd5b505afa92505050801561074e57506040513d6000823e3d601f19601f8201168201806040525081019061074b9190610910565b60015b6107575761075c565b809250505b5b8192505050919050565b60008151905061077681610e22565b92915050565b600082601f83011261078d57600080fd5b81356107a061079b82610c37565b610c0a565b915081818352602084019350602081019050838560208402820111156107c557600080fd5b60005b838110156107f557816107db88826107ff565b8452602084019350602083019250506001810190506107c8565b5050505092915050565b60008135905061080e81610e39565b92915050565b60008135905061082381610e50565b92915050565b600082601f83011261083a57600080fd5b815161084d61084882610c5f565b610c0a565b9150808252602083016020830185838301111561086957600080fd5b610874838284610dde565b50505092915050565b60006020828403121561088f57600080fd5b600061089d84828501610767565b91505092915050565b6000602082840312156108b857600080fd5b600082013567ffffffffffffffff8111156108d257600080fd5b6108de8482850161077c565b91505092915050565b6000602082840312156108f957600080fd5b600061090784828501610814565b91505092915050565b60006020828403121561092257600080fd5b600082015167ffffffffffffffff81111561093c57600080fd5b61094884828501610829565b91505092915050565b600061095d838361098c565b60208301905092915050565b60006109758383610a9b565b905092915050565b61098681610d84565b82525050565b61099581610d2a565b82525050565b60006109a682610cab565b6109b08185610ce6565b93506109bb83610c8b565b8060005b838110156109ec5781516109d38882610951565b97506109de83610ccc565b9250506001810190506109bf565b5085935050505092915050565b6000610a0482610cb6565b610a0e8185610cf7565b935083602082028501610a2085610c9b565b8060005b85811015610a5c5784840389528151610a3d8582610969565b9450610a4883610cd9565b925060208a01995050600181019050610a24565b50829750879550505050505092915050565b610a7781610d3c565b82525050565b610a8681610d48565b82525050565b610a9581610d96565b82525050565b6000610aa682610cc1565b610ab08185610d08565b9350610ac0818560208601610dde565b610ac981610e11565b840191505092915050565b6000610ae1602f83610d19565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b6000602082019050610b4f600083018461097d565b92915050565b60006020820190508181036000830152610b6f818461099b565b905092915050565b60006020820190508181036000830152610b9181846109f9565b905092915050565b6000602082019050610bae6000830184610a6e565b92915050565b6000602082019050610bc96000830184610a7d565b92915050565b6000602082019050610be46000830184610a8c565b92915050565b60006020820190508181036000830152610c0381610ad4565b9050919050565b6000604051905081810181811067ffffffffffffffff82111715610c2d57600080fd5b8060405250919050565b600067ffffffffffffffff821115610c4e57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115610c7657600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610d3582610d64565b9050919050565b60008115159050919050565b6000819050919050565b6000610d5d82610d2a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610d8f82610dba565b9050919050565b6000610da182610da8565b9050919050565b6000610db382610d64565b9050919050565b6000610dc582610dcc565b9050919050565b6000610dd782610d64565b9050919050565b60005b83811015610dfc578082015181840152602081019050610de1565b83811115610e0b576000848401525b50505050565b6000601f19601f8301169050919050565b610e2b81610d2a565b8114610e3657600080fd5b50565b610e4281610d48565b8114610e4d57600080fd5b50565b610e5981610d52565b8114610e6457600080fd5b5056fea164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806338bc01b51461005c578063392e53cd1461008c5780637b103999146100aa578063c4d66de8146100c8578063dc6008e2146100e4575b600080fd5b610076600480360381019061007191906108a6565b610114565b6040516100839190610b55565b60405180910390f35b6100946101ec565b6040516100a19190610b99565b60405180910390f35b6100b2610242565b6040516100bf9190610bcf565b60405180910390f35b6100e260048036038101906100dd91906108e7565b610268565b005b6100fe60048036038101906100f991906108a6565b6103b2565b60405161010b9190610b77565b60405180910390f35b606060008251905060608167ffffffffffffffff8111801561013557600080fd5b506040519080825280602002602001820160405280156101645781602001602082028036833780820191505090505b50905060005b828110156101e15761018e85828151811061018157fe5b6020026020010151610460565b82828151811061019a57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808060010191505061016a565b508092505050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146102f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ed90610bea565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516103a79190610b3a565b60405180910390a150565b606060008251905060608167ffffffffffffffff811180156103d357600080fd5b5060405190808252806020026020018201604052801561040757816020015b60608152602001906001900390816103f25790505b50905060005b828110156104555761043185828151811061042457fe5b60200260200101516105e1565b82828151811061043d57fe5b6020026020010181905250808060010191505061040d565b508092505050919050565b6000806000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf856040518263ffffffff1660e01b81526004016104c09190610bb4565b60206040518083038186803b1580156104d857600080fd5b505afa1580156104ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610510919061087d565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146105d7578073ffffffffffffffffffffffffffffffffffffffff16633b3b57de856040518263ffffffff1660e01b815260040161057f9190610bb4565b60206040518083038186803b15801561059757600080fd5b505afa9250505080156105c857506040513d601f19601f820116820180604052508101906105c5919061087d565b60015b6105d1576105d6565b809250505b5b8192505050919050565b6060806000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf856040518263ffffffff1660e01b81526004016106419190610bb4565b60206040518083038186803b15801561065957600080fd5b505afa15801561066d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610691919061087d565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461075d578073ffffffffffffffffffffffffffffffffffffffff1663691f3431856040518263ffffffff1660e01b81526004016107009190610bb4565b60006040518083038186803b15801561071857600080fd5b505afa92505050801561074e57506040513d6000823e3d601f19601f8201168201806040525081019061074b9190610910565b60015b6107575761075c565b809250505b5b8192505050919050565b60008151905061077681610e22565b92915050565b600082601f83011261078d57600080fd5b81356107a061079b82610c37565b610c0a565b915081818352602084019350602081019050838560208402820111156107c557600080fd5b60005b838110156107f557816107db88826107ff565b8452602084019350602083019250506001810190506107c8565b5050505092915050565b60008135905061080e81610e39565b92915050565b60008135905061082381610e50565b92915050565b600082601f83011261083a57600080fd5b815161084d61084882610c5f565b610c0a565b9150808252602083016020830185838301111561086957600080fd5b610874838284610dde565b50505092915050565b60006020828403121561088f57600080fd5b600061089d84828501610767565b91505092915050565b6000602082840312156108b857600080fd5b600082013567ffffffffffffffff8111156108d257600080fd5b6108de8482850161077c565b91505092915050565b6000602082840312156108f957600080fd5b600061090784828501610814565b91505092915050565b60006020828403121561092257600080fd5b600082015167ffffffffffffffff81111561093c57600080fd5b61094884828501610829565b91505092915050565b600061095d838361098c565b60208301905092915050565b60006109758383610a9b565b905092915050565b61098681610d84565b82525050565b61099581610d2a565b82525050565b60006109a682610cab565b6109b08185610ce6565b93506109bb83610c8b565b8060005b838110156109ec5781516109d38882610951565b97506109de83610ccc565b9250506001810190506109bf565b5085935050505092915050565b6000610a0482610cb6565b610a0e8185610cf7565b935083602082028501610a2085610c9b565b8060005b85811015610a5c5784840389528151610a3d8582610969565b9450610a4883610cd9565b925060208a01995050600181019050610a24565b50829750879550505050505092915050565b610a7781610d3c565b82525050565b610a8681610d48565b82525050565b610a9581610d96565b82525050565b6000610aa682610cc1565b610ab08185610d08565b9350610ac0818560208601610dde565b610ac981610e11565b840191505092915050565b6000610ae1602f83610d19565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b6000602082019050610b4f600083018461097d565b92915050565b60006020820190508181036000830152610b6f818461099b565b905092915050565b60006020820190508181036000830152610b9181846109f9565b905092915050565b6000602082019050610bae6000830184610a6e565b92915050565b6000602082019050610bc96000830184610a7d565b92915050565b6000602082019050610be46000830184610a8c565b92915050565b60006020820190508181036000830152610c0381610ad4565b9050919050565b6000604051905081810181811067ffffffffffffffff82111715610c2d57600080fd5b8060405250919050565b600067ffffffffffffffff821115610c4e57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115610c7657600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610d3582610d64565b9050919050565b60008115159050919050565b6000819050919050565b6000610d5d82610d2a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610d8f82610dba565b9050919050565b6000610da182610da8565b9050919050565b6000610db382610d64565b9050919050565b6000610dc582610dcc565b9050919050565b6000610dd782610d64565b9050919050565b60005b83811015610dfc578082015181840152602081019050610de1565b83811115610e0b576000848401525b50505050565b6000601f19601f8301169050919050565b610e2b81610d2a565b8114610e3657600080fd5b50565b610e4281610d48565b8114610e4d57600080fd5b50565b610e5981610d52565b8114610e6457600080fd5b5056fea164736f6c634300060c000a", diff --git a/deployments/neonDevnet/ENSRegistry.json b/deployments/neonDevnet/ENSRegistry.json index 1ec8b1ab..a1e2d3c6 100644 --- a/deployments/neonDevnet/ENSRegistry.json +++ b/deployments/neonDevnet/ENSRegistry.json @@ -376,24 +376,24 @@ "type": "function" } ], - "transactionHash": "0x8e856f881e3a281aa213b7e0dfc652b333e7c7c54a7e6cec6a1d90fd1f7733c3", + "transactionHash": "0xfb872a42a5c849acdaa0ca6f108abb6d5c846523885db2d8dfd447ccc3bf06b6", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", "contractAddress": null, "transactionIndex": 0, - "gasUsed": "53531520", + "gasUsed": "53921280", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7d90702d236901dc75294aa712e7d3c61721c3694650e94b086b42426256e7bb", - "transactionHash": "0x8e856f881e3a281aa213b7e0dfc652b333e7c7c54a7e6cec6a1d90fd1f7733c3", + "blockHash": "0x508fd4ecd642b111e5a420b88a459d559306c6e2133f61379c01ddd4a62931c0", + "transactionHash": "0xfb872a42a5c849acdaa0ca6f108abb6d5c846523885db2d8dfd447ccc3bf06b6", "logs": [], - "blockNumber": 173996803, - "cumulativeGasUsed": "53531520", + "blockNumber": 178555100, + "cumulativeGasUsed": "53921280", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"label\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NewOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"NewResolver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"NewTTL\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"recordExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver_\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"ttl_\",\"type\":\"uint64\"}],\"name\":\"setRecord\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"resolver_\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"label\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"name\":\"setSubnodeOwner\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"label\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver_\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"ttl_\",\"type\":\"uint64\"}],\"name\":\"setSubnodeRecord\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"ttl_\",\"type\":\"uint64\"}],\"name\":\"setTTL\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ttl\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ENSRegistry.sol\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"}},\"title\":\"ENS registry\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ens/ENSRegistry.sol\":\"ENSRegistry\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"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\",\"keccak256\":\"0xe00dbdea09d17d41c2c14266e6e1b6b95938c0d374b266bb44a91cfcf0495612\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b50326000808060001b815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611253806100776000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635b0fc9c3116100715780635b0fc9c3146102b15780635ef2c7f0146102ff578063a22cb4651461038b578063cf408823146103db578063e985e9c51461045d578063f79fe538146104d7576100b4565b80630178b8bf146100b957806302571be31461011157806306ab59231461016957806314ab9038146101d557806316a25cbd146102175780631896f70a14610263575b600080fd5b6100e5600480360360208110156100cf57600080fd5b810190808035906020019092919050505061051b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61013d6004803603602081101561012757600080fd5b810190808035906020019092919050505061055a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101bf6004803603606081101561017f57600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105dd565b6040518082815260200191505060405180910390f35b610215600480360360408110156101eb57600080fd5b8101908080359060200190929190803567ffffffffffffffff169060200190929190505050610812565b005b6102436004803603602081101561022d57600080fd5b81019080803590602001909291905050506109e6565b604051808267ffffffffffffffff16815260200191505060405180910390f35b6102af6004803603604081101561027957600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a19565b005b6102fd600480360360408110156102c757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c11565b005b610389600480360360a081101561031557600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610e09565b005b6103d9600480360360408110156103a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610e2b565b005b61045b600480360360808110156103f157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610f2a565b005b6104bf6004803603604081101561047357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f45565b60405180821515815260200191505060405180910390f35b610503600480360360208110156104ed57600080fd5b8101908080359060200190929190505050610fd9565b60405180821515815260200191505060405180910390f35b600080600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156105d35760009150506105d8565b809150505b919050565b600083600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806106da5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61072f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b6000868660405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090508460008083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085877fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8287604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a38093505050509392505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061090d5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b8260008086815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550837f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6884604051808267ffffffffffffffff16815260200191505060405180910390a250505050565b600080600083815260200190815260200160002060010160149054906101000a900467ffffffffffffffff169050919050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610b145750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b8260008086815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550837f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a084604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610d0c5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b8260008086815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550837fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26684604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b6000610e168686866105dd565b9050610e23818484611047565b505050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610f348484610c11565b610f3f848383611047565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60008084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611152578160008085815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25b60008084815260200190815260200160002060010160149054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1614611215578060008085815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6882604051808267ffffffffffffffff16815260200191505060405180910390a25b50505056fe454e5352656769737472793a20726576657274656420627920617574686f7269736564206d6f646966696572a164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635b0fc9c3116100715780635b0fc9c3146102b15780635ef2c7f0146102ff578063a22cb4651461038b578063cf408823146103db578063e985e9c51461045d578063f79fe538146104d7576100b4565b80630178b8bf146100b957806302571be31461011157806306ab59231461016957806314ab9038146101d557806316a25cbd146102175780631896f70a14610263575b600080fd5b6100e5600480360360208110156100cf57600080fd5b810190808035906020019092919050505061051b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61013d6004803603602081101561012757600080fd5b810190808035906020019092919050505061055a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101bf6004803603606081101561017f57600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105dd565b6040518082815260200191505060405180910390f35b610215600480360360408110156101eb57600080fd5b8101908080359060200190929190803567ffffffffffffffff169060200190929190505050610812565b005b6102436004803603602081101561022d57600080fd5b81019080803590602001909291905050506109e6565b604051808267ffffffffffffffff16815260200191505060405180910390f35b6102af6004803603604081101561027957600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a19565b005b6102fd600480360360408110156102c757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c11565b005b610389600480360360a081101561031557600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610e09565b005b6103d9600480360360408110156103a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610e2b565b005b61045b600480360360808110156103f157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610f2a565b005b6104bf6004803603604081101561047357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f45565b60405180821515815260200191505060405180910390f35b610503600480360360208110156104ed57600080fd5b8101908080359060200190929190505050610fd9565b60405180821515815260200191505060405180910390f35b600080600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156105d35760009150506105d8565b809150505b919050565b600083600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806106da5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61072f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b6000868660405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090508460008083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085877fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8287604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a38093505050509392505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061090d5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b8260008086815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550837f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6884604051808267ffffffffffffffff16815260200191505060405180910390a250505050565b600080600083815260200190815260200160002060010160149054906101000a900467ffffffffffffffff169050919050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610b145750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b8260008086815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550837f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a084604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610d0c5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061121b602c913960400191505060405180910390fd5b8260008086815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550837fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26684604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b6000610e168686866105dd565b9050610e23818484611047565b505050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610f348484610c11565b610f3f848383611047565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60008084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611152578160008085815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25b60008084815260200190815260200160002060010160149054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1614611215578060008085815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6882604051808267ffffffffffffffff16815260200191505060405180910390a25b50505056fe454e5352656769737472793a20726576657274656420627920617574686f7269736564206d6f646966696572a164736f6c634300060c000a", diff --git a/deployments/neonDevnet/ENSReverseRegistrar.json b/deployments/neonDevnet/ENSReverseRegistrar.json index cdc44edf..f054df46 100644 --- a/deployments/neonDevnet/ENSReverseRegistrar.json +++ b/deployments/neonDevnet/ENSReverseRegistrar.json @@ -171,7 +171,7 @@ "type": "function" } ], - "transactionHash": "0x7c0f450722b503fc6a836fdb009f5f7d30c53ebc31599b58e83082b12ee9276b", + "transactionHash": "0x57ae6885e36a19ffd46ad47b4ba57503499abc0c1de0836ee2a381b757d1f1ab", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -179,16 +179,16 @@ "transactionIndex": 0, "gasUsed": "43669200", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x08d1f61351145e233027d39766d9e4f285dfb6b6e88d6cbf527f39e508714585", - "transactionHash": "0x7c0f450722b503fc6a836fdb009f5f7d30c53ebc31599b58e83082b12ee9276b", + "blockHash": "0xa256097fd964c2196b4d0e1d1113a2e099be64ed9aa986945428348920923a46", + "transactionHash": "0x57ae6885e36a19ffd46ad47b4ba57503499abc0c1de0836ee2a381b757d1f1ab", "logs": [], - "blockNumber": 173996822, + "blockNumber": 178555136, "cumulativeGasUsed": "43669200", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "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\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ADDR_REVERSE_NODE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver_\",\"type\":\"address\"}],\"name\":\"claimWithResolver\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ENSRegistry\",\"name\":\"registry_\",\"type\":\"address\"},{\"internalType\":\"contract ENSNameResolver\",\"name\":\"resolver_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}],\"name\":\"node\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"contract ENSRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolver\",\"outputs\":[{\"internalType\":\"contract ENSNameResolver\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Base on https://github.com/ensdomains/ens/blob/ff0f41747c05f1598973b0fe7ad0d9e09565dfcd/contracts/ReverseRegistrar.sol\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"},\"initialize(address,address)\":{\"params\":{\"registry_\":\"ENS registry address\",\"resolver_\":\"ENS name resolver address\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}}},\"title\":\"ENS reverse registrar\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(address,address)\":{\"notice\":\"Initializes `ENSReverseRegistrar` contract\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ens/ENSReverseRegistrar.sol\":\"ENSReverseRegistrar\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"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\",\"keccak256\":\"0xe54172c033f0a3e59a8ec5ae72aeac02a35b4341331e2698baeb31fa5e543f5f\",\"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/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\",\"keccak256\":\"0xe00dbdea09d17d41c2c14266e6e1b6b95938c0d374b266bb44a91cfcf0495612\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xcedc0ece74976c6a3d22fc615baa0cb171e510ac53688a803211606c438dfdf2\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0xc67d8bdd4904684e5d3388f7ca7d18c7d407058d6b548d8c591404c758a1ac60\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x1d2d4b21f59225fbefe0e5aaff87aff8f11afe5281745934d595e15770557ead\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610df8806100606000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063485cc95511610066578063485cc955146101bc5780637b103999146102205780637cf8a2eb14610254578063bffbe61c14610272578063c47f0027146102ca57610093565b806304f3bcec146100985780630f5a5466146100cc5780631e83409a14610144578063392e53cd1461019c575b600080fd5b6100a0610399565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61012e600480360360408110156100e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506103bf565b6040518082815260200191505060405180910390f35b6101866004803603602081101561015a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506103d3565b6040518082815260200191505060405180910390f35b6101a46103e7565b60405180821515815260200191505060405180910390f35b61021e600480360360408110156101d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061043d565b005b6102286105f5565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61025c61061b565b6040518082815260200191505060405180910390f35b6102b46004803603602081101561028857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610642565b6040518082815260200191505060405180910390f35b610383600480360360208110156102e057600080fd5b81019080803590602001906401000000008111156102fd57600080fd5b82018360208201111561030f57600080fd5b8035906020019184600183028401116401000000008311171561033157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506106bb565b6040518082815260200191505060405180910390f35b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006103cb83836107ef565b905092915050565b60006103e08260006107ef565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146104e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180610dbd602f913960400191505060405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b81565b60007f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b6106878373ffffffffffffffffffffffffffffffffffffffff16610d4d565b6040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b6000806106ea30600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166107ef565b9050600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637737221382856040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610781578082015181840152602081019050610766565b50505050905090810190601f1680156107ae5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156107ce57600080fd5b505af11580156107e2573d6000803e3d6000fd5b5050505080915050919050565b6000806108113373ffffffffffffffffffffffffffffffffffffffff16610d4d565b905060007f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b8260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156108de57600080fd5b505afa1580156108f2573d6000803e3d6000fd5b505050506040513d602081101561090857600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614158015610a315750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156109c657600080fd5b505afa1580156109da573d6000803e3d6000fd5b505050506040513d60208110156109f057600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15610c13573073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b6757600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306ab59237f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b85306040518463ffffffff1660e01b8152600401808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019350505050602060405180830381600087803b158015610b2757600080fd5b505af1158015610b3b573d6000803e3d6000fd5b505050506040513d6020811015610b5157600080fd5b8101908080519060200190929190505050503090505b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631896f70a83876040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b158015610bfa57600080fd5b505af1158015610c0e573d6000803e3d6000fd5b505050505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d4157600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306ab59237f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b85896040518463ffffffff1660e01b8152600401808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019350505050602060405180830381600087803b158015610d0457600080fd5b505af1158015610d18573d6000803e3d6000fd5b505050506040513d6020811015610d2e57600080fd5b8101908080519060200190929190505050505b81935050505092915050565b6000807f303132333435363738396162636465660000000000000000000000000000000060285b6000811115610daa5760018103905081600f86161a815360108504945060018103905081600f86161a8153601085049450610d74565b5060286000209150508091505091905056fe496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a6572a164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063485cc95511610066578063485cc955146101bc5780637b103999146102205780637cf8a2eb14610254578063bffbe61c14610272578063c47f0027146102ca57610093565b806304f3bcec146100985780630f5a5466146100cc5780631e83409a14610144578063392e53cd1461019c575b600080fd5b6100a0610399565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61012e600480360360408110156100e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506103bf565b6040518082815260200191505060405180910390f35b6101866004803603602081101561015a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506103d3565b6040518082815260200191505060405180910390f35b6101a46103e7565b60405180821515815260200191505060405180910390f35b61021e600480360360408110156101d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061043d565b005b6102286105f5565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61025c61061b565b6040518082815260200191505060405180910390f35b6102b46004803603602081101561028857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610642565b6040518082815260200191505060405180910390f35b610383600480360360208110156102e057600080fd5b81019080803590602001906401000000008111156102fd57600080fd5b82018360208201111561030f57600080fd5b8035906020019184600183028401116401000000008311171561033157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506106bb565b6040518082815260200191505060405180910390f35b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006103cb83836107ef565b905092915050565b60006103e08260006107ef565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146104e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180610dbd602f913960400191505060405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b81565b60007f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b6106878373ffffffffffffffffffffffffffffffffffffffff16610d4d565b6040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b6000806106ea30600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166107ef565b9050600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637737221382856040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610781578082015181840152602081019050610766565b50505050905090810190601f1680156107ae5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156107ce57600080fd5b505af11580156107e2573d6000803e3d6000fd5b5050505080915050919050565b6000806108113373ffffffffffffffffffffffffffffffffffffffff16610d4d565b905060007f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b8260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156108de57600080fd5b505afa1580156108f2573d6000803e3d6000fd5b505050506040513d602081101561090857600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614158015610a315750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156109c657600080fd5b505afa1580156109da573d6000803e3d6000fd5b505050506040513d60208110156109f057600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15610c13573073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b6757600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306ab59237f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b85306040518463ffffffff1660e01b8152600401808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019350505050602060405180830381600087803b158015610b2757600080fd5b505af1158015610b3b573d6000803e3d6000fd5b505050506040513d6020811015610b5157600080fd5b8101908080519060200190929190505050503090505b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631896f70a83876040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b158015610bfa57600080fd5b505af1158015610c0e573d6000803e3d6000fd5b505050505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d4157600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306ab59237f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260001b85896040518463ffffffff1660e01b8152600401808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019350505050602060405180830381600087803b158015610d0457600080fd5b505af1158015610d18573d6000803e3d6000fd5b505050506040513d6020811015610d2e57600080fd5b8101908080519060200190929190505050505b81935050505092915050565b6000807f303132333435363738396162636465660000000000000000000000000000000060285b6000811115610daa5760018103905081600f86161a815360108504945060018103905081600f86161a8153601085049450610d74565b5060286000209150508091505091905056fe496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a6572a164736f6c634300060c000a", diff --git a/deployments/neonDevnet/ExternalAccountRegistry.json b/deployments/neonDevnet/ExternalAccountRegistry.json index 32cd6b20..dcf76a2d 100644 --- a/deployments/neonDevnet/ExternalAccountRegistry.json +++ b/deployments/neonDevnet/ExternalAccountRegistry.json @@ -236,7 +236,7 @@ "type": "function" } ], - "transactionHash": "0xd31152fbbb7e51f8ecdc84610a8c9c099cfd4995ea2f1f4a005a14318f12fcef", + "transactionHash": "0x09f8e8b154df9a1b6dd2524ed22f233c717f114e8c5f69f8efbb62822d2843ab", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -244,16 +244,16 @@ "transactionIndex": 0, "gasUsed": "47733840", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x37933bb07475cdf7d0ff8f3a42ebf882188b76ad5a0338530683513515a5104a", - "transactionHash": "0xd31152fbbb7e51f8ecdc84610a8c9c099cfd4995ea2f1f4a005a14318f12fcef", + "blockHash": "0x5a30b560983eecd83d54b734bf1fb4a4c73c12ea3aa54ae8604fc73da24dd57e", + "transactionHash": "0x09f8e8b154df9a1b6dd2524ed22f233c717f114e8c5f69f8efbb62822d2843ab", "logs": [], - "blockNumber": 173996844, + "blockNumber": 178555176, "cumulativeGasUsed": "47733840", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"AccountOwnerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"AccountOwnerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"AccountProofAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"AccountProofRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"addAccountOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"addAccountProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"removeAccountOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"removeAccountProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"verifyAccountOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"verifyAccountOwnerAtBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"verifyAccountProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"verifyAccountProofAtBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"details\":\"An account can call the registry to add (`addAccountOwner`) or remove (`removeAccountOwner`) its own owners. When the owner has been added, information about that fact will live in the registry forever. Removing an owner only affects the future blocks (until the owner is re-added). Given the fact, there is no way to sign the data using a contract based wallet, we created a registry to store signed by the key wallet proofs. ERC-1271 allows removing a signer after the signature was created. Thus store the signature for the later use doesn't guarantee the signer is still has access to that smart account. Because of that, the ERC1271's `isValidSignature()` cannot be used in e.g. `PaymentRegistry`.* An account can call the registry to add (`addAccountProof`) or remove (`removeAccountProof`) proof hash. When the proof has been added, information about that fact will live in the registry forever. Removing a proof only affects the future blocks (until the proof is re-added).\",\"events\":{\"AccountOwnerAdded(address,address)\":{\"details\":\"Emitted when the new owner is added\",\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"}},\"AccountOwnerRemoved(address,address)\":{\"details\":\"Emitted when the existing owner is removed\",\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"}},\"AccountProofAdded(address,bytes32)\":{\"details\":\"Emitted when the new proof is added\",\"params\":{\"account\":\"account address\",\"hash\":\"proof hash\"}},\"AccountProofRemoved(address,bytes32)\":{\"details\":\"Emitted when the existing proof is removed\",\"params\":{\"account\":\"account address\",\"hash\":\"proof hash\"}}},\"kind\":\"dev\",\"methods\":{\"addAccountOwner(address)\":{\"params\":{\"owner\":\"owner address\"}},\"addAccountProof(bytes32)\":{\"params\":{\"hash\":\"proof hash\"}},\"removeAccountOwner(address)\":{\"params\":{\"owner\":\"owner address\"}},\"removeAccountProof(bytes32)\":{\"params\":{\"hash\":\"proof hash\"}},\"verifyAccountOwner(address,address)\":{\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"},\"returns\":{\"_0\":\"true on correct account owner\"}},\"verifyAccountOwnerAtBlock(address,address,uint256)\":{\"params\":{\"account\":\"account address\",\"blockNumber\":\"block number to verify\",\"owner\":\"owner address\"},\"returns\":{\"_0\":\"true on correct account owner\"}},\"verifyAccountProof(address,bytes32)\":{\"params\":{\"account\":\"account address\",\"hash\":\"proof hash\"},\"returns\":{\"_0\":\"true on correct account proof\"}},\"verifyAccountProofAtBlock(address,bytes32,uint256)\":{\"params\":{\"account\":\"account address\",\"blockNumber\":\"block number to verify\",\"hash\":\"proof hash\"},\"returns\":{\"_0\":\"true on correct account proof\"}}},\"title\":\"External account registry\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addAccountOwner(address)\":{\"notice\":\"Adds a new account owner\"},\"addAccountProof(bytes32)\":{\"notice\":\"Adds a new account proof\"},\"removeAccountOwner(address)\":{\"notice\":\"Removes existing account owner\"},\"removeAccountProof(bytes32)\":{\"notice\":\"Removes existing account proof\"},\"verifyAccountOwner(address,address)\":{\"notice\":\"Verifies the owner of the account at current block\"},\"verifyAccountOwnerAtBlock(address,address,uint256)\":{\"notice\":\"Verifies the owner of the account at specific block\"},\"verifyAccountProof(address,bytes32)\":{\"notice\":\"Verifies the proof of the account at current block\"},\"verifyAccountProofAtBlock(address,bytes32,uint256)\":{\"notice\":\"Verifies the proof of the account at specific block\"}},\"notice\":\"Global registry for keys and external (outside of the platform) contract based wallets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/external/ExternalAccountRegistry.sol\":\"ExternalAccountRegistry\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"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/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\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b50610fff806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806394000b021161005b57806394000b0214610227578063bb890d3f14610255578063d543c34a146102cf578063e278cfc6146102fd57610088565b806334d323a41461008d57806359b52ef8146101115780638a3133781461017f5780638ecc1365146101e3575b600080fd5b6100f9600480360360608110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610341565b60405180821515815260200191505060405180910390f35b6101676004803603606081101561012757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919050505061040c565b60405180821515815260200191505060405180910390f35b6101cb6004803603604081101561019557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506104ab565b60405180821515815260200191505060405180910390f35b610225600480360360208110156101f957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061053f565b005b6102536004803603602081101561023d57600080fd5b8101908080359060200190929190505050610860565b005b6102b76004803603604081101561026b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506109f1565b60405180821515815260200191505060405180910390f35b6102fb600480360360208110156102e557600080fd5b8101908080359060200190929190505050610ab1565b005b61033f6004803603602081101561031357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb2565b005b6000610403826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610eb190919063ffffffff16565b90509392505050565b60006104a2826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610eb190919063ffffffff16565b90509392505050565b60006105376000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008481526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156105c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180610f14602d913960400191505060405180910390fd5b61067b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b156106d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180610f6e602d913960400191505060405180910390fd5b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff02191690831515021790555060008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f27e282f7712c5b4617277759c834b86d163dfc1aad25c8c3c5926a1c9e5644683382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b6108ea6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008381526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b61093f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180610fc7602c913960400191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000838152602001908152602001600020600101819055507f87dde712783ad4895642c7a875998317a71cf424a2444eb79545ce3795431ff93382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a150565b6000610aa96000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b905092915050565b610b3b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008381526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b15610b91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180610f41602d913960400191505060405180910390fd5b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101600083815260200190815260200160002060000160006101000a81548160ff02191690831515021790555060008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000838152602001908152602001600020600101819055507f4075b367eed0513a54aa39c287c66d6ae98e5df6f73ac087b26b8f89d05d1aa83382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a150565b610d686000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b610dbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180610f9b602c913960400191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f1ce3cbbc43ee231e5b950332f2b0b9dd7d349291a3ee411ce5c5c7ed745661bb3382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b60008060009050836000015115610ef657600084602001511415610ed85760019050610ef5565b6000831415610eea5760019050610ef4565b8284602001511190505b5b5b8091505092915050565b6000610f0c8243610eb1565b905091905056fe45787465726e616c4163636f756e7452656769737472793a2063616e6e6f742061646420307830206f776e657245787465726e616c4163636f756e7452656769737472793a2070726f6f6620616c72656164792065786973747345787465726e616c4163636f756e7452656769737472793a206f776e657220616c72656164792065786973747345787465726e616c4163636f756e7452656769737472793a206f776e657220646f65736e277420657869737445787465726e616c4163636f756e7452656769737472793a2070726f6f6620646f65736e2774206578697374a164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c806394000b021161005b57806394000b0214610227578063bb890d3f14610255578063d543c34a146102cf578063e278cfc6146102fd57610088565b806334d323a41461008d57806359b52ef8146101115780638a3133781461017f5780638ecc1365146101e3575b600080fd5b6100f9600480360360608110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610341565b60405180821515815260200191505060405180910390f35b6101676004803603606081101561012757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919050505061040c565b60405180821515815260200191505060405180910390f35b6101cb6004803603604081101561019557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506104ab565b60405180821515815260200191505060405180910390f35b610225600480360360208110156101f957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061053f565b005b6102536004803603602081101561023d57600080fd5b8101908080359060200190929190505050610860565b005b6102b76004803603604081101561026b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506109f1565b60405180821515815260200191505060405180910390f35b6102fb600480360360208110156102e557600080fd5b8101908080359060200190929190505050610ab1565b005b61033f6004803603602081101561031357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb2565b005b6000610403826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610eb190919063ffffffff16565b90509392505050565b60006104a2826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610eb190919063ffffffff16565b90509392505050565b60006105376000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008481526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156105c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180610f14602d913960400191505060405180910390fd5b61067b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b156106d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180610f6e602d913960400191505060405180910390fd5b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff02191690831515021790555060008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f27e282f7712c5b4617277759c834b86d163dfc1aad25c8c3c5926a1c9e5644683382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b6108ea6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008381526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b61093f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180610fc7602c913960400191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000838152602001908152602001600020600101819055507f87dde712783ad4895642c7a875998317a71cf424a2444eb79545ce3795431ff93382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a150565b6000610aa96000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b905092915050565b610b3b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008381526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b15610b91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180610f41602d913960400191505060405180910390fd5b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101600083815260200190815260200160002060000160006101000a81548160ff02191690831515021790555060008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000838152602001908152602001600020600101819055507f4075b367eed0513a54aa39c287c66d6ae98e5df6f73ac087b26b8f89d05d1aa83382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a150565b610d686000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050610f00565b610dbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180610f9b602c913960400191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f1ce3cbbc43ee231e5b950332f2b0b9dd7d349291a3ee411ce5c5c7ed745661bb3382604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b60008060009050836000015115610ef657600084602001511415610ed85760019050610ef5565b6000831415610eea5760019050610ef4565b8284602001511190505b5b5b8091505092915050565b6000610f0c8243610eb1565b905091905056fe45787465726e616c4163636f756e7452656769737472793a2063616e6e6f742061646420307830206f776e657245787465726e616c4163636f756e7452656769737472793a2070726f6f6620616c72656164792065786973747345787465726e616c4163636f756e7452656769737472793a206f776e657220616c72656164792065786973747345787465726e616c4163636f756e7452656769737472793a206f776e657220646f65736e277420657869737445787465726e616c4163636f756e7452656769737472793a2070726f6f6620646f65736e2774206578697374a164736f6c634300060c000a", diff --git a/deployments/neonDevnet/Gateway.json b/deployments/neonDevnet/Gateway.json index 45bdf811..99ba2f01 100644 --- a/deployments/neonDevnet/Gateway.json +++ b/deployments/neonDevnet/Gateway.json @@ -346,7 +346,7 @@ "type": "function" } ], - "transactionHash": "0x527b68d567e57e392dc2f25c13b067067ef03c7870f287b8eb0e3ade6aae7dbb", + "transactionHash": "0x69796207b7731aa6b5ba6f2b523ccc96829c984b00bbf003e3c569a4afbfa533", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -354,17 +354,17 @@ "transactionIndex": 0, "gasUsed": "87751880", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xcc266b2fc3e13db0f6e673b86090219a1f625cf98f00df620f1114086cae9339", - "transactionHash": "0x527b68d567e57e392dc2f25c13b067067ef03c7870f287b8eb0e3ade6aae7dbb", + "blockHash": "0x1e65d687b6a2e7450ba3ad09b12f6d7a0e00ee96c453448e3237cd954e549462", + "transactionHash": "0x69796207b7731aa6b5ba6f2b523ccc96829c984b00bbf003e3c569a4afbfa533", "logs": [], - "blockNumber": 173996859, + "blockNumber": 178555239, "cumulativeGasUsed": "87751880", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", - "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"batch\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"succeeded\",\"type\":\"bool\"}],\"name\":\"BatchDelegated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"}],\"name\":\"delegateBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"}],\"name\":\"delegateBatchWithGasPrice\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"batches\",\"type\":\"bytes[]\"},{\"internalType\":\"bool\",\"name\":\"revertOnFailure\",\"type\":\"bool\"}],\"name\":\"delegateBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"externalAccountRegistry\",\"outputs\":[{\"internalType\":\"contract ExternalAccountRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountNextNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"internalType\":\"struct Gateway.DelegatedBatch\",\"name\":\"delegatedBatch\",\"type\":\"tuple\"}],\"name\":\"hashDelegatedBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct Gateway.DelegatedBatchWithGasPrice\",\"name\":\"delegatedBatch\",\"type\":\"tuple\"}],\"name\":\"hashDelegatedBatchWithGasPrice\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ExternalAccountRegistry\",\"name\":\"externalAccountRegistry_\",\"type\":\"address\"},{\"internalType\":\"contract PersonalAccountRegistry\",\"name\":\"personalAccountRegistry_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"personalAccountRegistry\",\"outputs\":[{\"internalType\":\"contract PersonalAccountRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatchFromAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"events\":{\"BatchDelegated(address,bytes,bool)\":{\"details\":\"Emitted when the single batch is delegated\",\"params\":{\"batch\":\"batch\",\"sender\":\"sender address\",\"succeeded\":\"if succeeded\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"},\"delegateBatch(address,uint256,address[],bytes[],bytes)\":{\"details\":\"Use `hashDelegatedBatch` to create sender message payload. `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"nonce\":\"next account nonce\",\"senderSignature\":\"sender signature\",\"to\":\"array of batch recipients contracts\"}},\"delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)\":{\"details\":\"Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice) `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"nonce\":\"next account nonce\",\"senderSignature\":\"sender signature\",\"to\":\"array of batch recipients contracts\"}},\"delegateBatches(bytes[],bool)\":{\"details\":\"It will revert when all batches fail\",\"params\":{\"batches\":\"array of batches\",\"revertOnFailure\":\"reverts on any error\"}},\"getAccountNextNonce(address)\":{\"params\":{\"account\":\"account address\"},\"returns\":{\"_0\":\"next nonce\"}},\"hashDelegatedBatch((address,uint256,address[],bytes[]))\":{\"params\":{\"delegatedBatch\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))\":{\"params\":{\"delegatedBatch\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"initialize(address,address)\":{\"params\":{\"externalAccountRegistry_\":\"`ExternalAccountRegistry` contract address\",\"personalAccountRegistry_\":\"`PersonalAccountRegistry` contract address\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"sendBatch(address[],bytes[])\":{\"details\":\"`GatewayRecipient` context api: `_getContextAccount` will return `msg.sender` `_getContextSender` will return `msg.sender`\",\"params\":{\"data\":\"array of batch data\",\"to\":\"array of batch recipients contracts\"}},\"sendBatchFromAccount(address,address[],bytes[])\":{\"details\":\"`GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return `msg.sender`\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"to\":\"array of batch recipients contracts\"}}},\"title\":\"Gateway\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"delegateBatch(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account\"},\"delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account (with gas price)\"},\"delegateBatches(bytes[],bool)\":{\"notice\":\"Delegates multiple batches\"},\"getAccountNextNonce(address)\":{\"notice\":\"Gets next account nonce\"},\"hashDelegatedBatch((address,uint256,address[],bytes[]))\":{\"notice\":\"Hashes `DelegatedBatch` message payload\"},\"hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))\":{\"notice\":\"Hashes `DelegatedBatchWithGasPrice` message payload\"},\"initialize(address,address)\":{\"notice\":\"Initializes `Gateway` contract\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"sendBatch(address[],bytes[])\":{\"notice\":\"Sends batch\"},\"sendBatchFromAccount(address,address[],bytes[])\":{\"notice\":\"Sends batch from the account\"}},\"notice\":\"GSN replacement\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/gateway/Gateway.sol\":\"Gateway\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/common/access/Controlled.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\n/**\\n * @title Controlled\\n *\\n * @dev Contract module which provides an access control mechanism.\\n * It ensures there is only one controlling account of the smart contract\\n * and grants that account exclusive access to specific functions.\\n *\\n * The controller account will be the one that deploys the contract.\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski \\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/Gateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../common/libs/ECDSALib.sol\\\";\\nimport \\\"../common/libs/SafeMathLib.sol\\\";\\nimport \\\"../common/lifecycle/Initializable.sol\\\";\\nimport \\\"../common/signature/SignatureValidator.sol\\\";\\nimport \\\"../external/ExternalAccountRegistry.sol\\\";\\nimport \\\"../personal/PersonalAccountRegistry.sol\\\";\\n\\n\\n/**\\n * @title Gateway\\n *\\n * @notice GSN replacement\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski \\n */\\ncontract Gateway is Initializable, SignatureValidator {\\n using ECDSALib for bytes32;\\n using SafeMathLib for uint256;\\n\\n struct DelegatedBatch {\\n address account;\\n uint256 nonce;\\n address[] to;\\n bytes[] data;\\n }\\n\\n struct DelegatedBatchWithGasPrice {\\n address account;\\n uint256 nonce;\\n address[] to;\\n bytes[] data;\\n uint256 gasPrice;\\n }\\n\\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256(\\n \\\"DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)\\\"\\n );\\n\\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256(\\n \\\"DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)\\\"\\n );\\n\\n ExternalAccountRegistry public externalAccountRegistry;\\n PersonalAccountRegistry public personalAccountRegistry;\\n\\n mapping(address => uint256) private accountNonce;\\n\\n // events\\n\\n /**\\n * @dev Emitted when the single batch is delegated\\n * @param sender sender address\\n * @param batch batch\\n * @param succeeded if succeeded\\n */\\n event BatchDelegated(\\n address sender,\\n bytes batch,\\n bool succeeded\\n );\\n\\n /**\\n * @dev Public constructor\\n */\\n constructor() public Initializable() SignatureValidator() {}\\n\\n // external functions\\n\\n /**\\n * @notice Initializes `Gateway` contract\\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\\n */\\n function initialize(\\n ExternalAccountRegistry externalAccountRegistry_,\\n PersonalAccountRegistry personalAccountRegistry_\\n )\\n external\\n onlyInitializer\\n {\\n externalAccountRegistry = externalAccountRegistry_;\\n personalAccountRegistry = personalAccountRegistry_;\\n }\\n\\n // public functions\\n\\n /**\\n * @notice Sends batch\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `msg.sender`\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatch(\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n {\\n _sendBatch(\\n msg.sender,\\n msg.sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Sends batch from the account\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param account account address\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatchFromAccount(\\n address account,\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n {\\n _sendBatch(\\n account,\\n msg.sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates batch from the account\\n * @dev Use `hashDelegatedBatch` to create sender message payload.\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatch(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n {\\n require(\\n nonce > accountNonce[account],\\n \\\"Gateway: nonce is lower than current account nonce\\\"\\n );\\n\\n address sender = _hashDelegatedBatch(\\n account,\\n nonce,\\n to,\\n data\\n ).recoverAddress(senderSignature);\\n\\n accountNonce[account] = nonce;\\n\\n _sendBatch(\\n account,\\n sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates batch from the account (with gas price)\\n *\\n * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatchWithGasPrice(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n {\\n require(\\n nonce > accountNonce[account],\\n \\\"Gateway: nonce is lower than current account nonce\\\"\\n );\\n\\n address sender = _hashDelegatedBatchWithGasPrice(\\n account,\\n nonce,\\n to,\\n data,\\n tx.gasprice\\n ).recoverAddress(senderSignature);\\n\\n accountNonce[account] = nonce;\\n\\n _sendBatch(\\n account,\\n sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates multiple batches\\n * @dev It will revert when all batches fail\\n * @param batches array of batches\\n * @param revertOnFailure reverts on any error\\n */\\n function delegateBatches(\\n bytes[] memory batches,\\n bool revertOnFailure\\n )\\n public\\n {\\n require(\\n batches.length > 0,\\n \\\"Gateway: cannot delegate empty batches\\\"\\n );\\n\\n bool anySucceeded;\\n\\n for (uint256 i = 0; i < batches.length; i++) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool succeeded,) = address(this).call(batches[i]);\\n\\n if (revertOnFailure) {\\n require(\\n succeeded,\\n \\\"Gateway: batch reverted\\\"\\n );\\n } else if (succeeded && !anySucceeded) {\\n anySucceeded = true;\\n }\\n\\n emit BatchDelegated(\\n msg.sender,\\n batches[i],\\n succeeded\\n );\\n }\\n\\n if (!anySucceeded) {\\n revert(\\\"Gateway: all batches reverted\\\");\\n }\\n }\\n\\n // public functions (views)\\n\\n /**\\n * @notice Hashes `DelegatedBatch` message payload\\n * @param delegatedBatch struct\\n * @return hash\\n */\\n function hashDelegatedBatch(\\n DelegatedBatch memory delegatedBatch\\n )\\n public\\n view\\n returns (bytes32)\\n {\\n return _hashDelegatedBatch(\\n delegatedBatch.account,\\n delegatedBatch.nonce,\\n delegatedBatch.to,\\n delegatedBatch.data\\n );\\n }\\n\\n /**\\n * @notice Hashes `DelegatedBatchWithGasPrice` message payload\\n * @param delegatedBatch struct\\n * @return hash\\n */\\n function hashDelegatedBatchWithGasPrice(\\n DelegatedBatchWithGasPrice memory delegatedBatch\\n )\\n public\\n view\\n returns (bytes32)\\n {\\n return _hashDelegatedBatchWithGasPrice(\\n delegatedBatch.account,\\n delegatedBatch.nonce,\\n delegatedBatch.to,\\n delegatedBatch.data,\\n delegatedBatch.gasPrice\\n );\\n }\\n\\n // external functions (views)\\n\\n /**\\n * @notice Gets next account nonce\\n * @param account account address\\n * @return next nonce\\n */\\n function getAccountNextNonce(\\n address account\\n )\\n external\\n view\\n returns (uint256)\\n {\\n return accountNonce[account].add(1);\\n }\\n\\n // private functions\\n\\n function _sendBatch(\\n address account,\\n address sender,\\n address[] memory to,\\n bytes[] memory data\\n )\\n private\\n {\\n require(\\n account != address(0),\\n \\\"Gateway: cannot send from 0x0 account\\\"\\n );\\n require(\\n to.length > 0,\\n \\\"Gateway: cannot send empty batch\\\"\\n );\\n require(\\n data.length == to.length,\\n \\\"Gateway: invalid batch\\\"\\n );\\n\\n if (account != sender) {\\n require(\\n personalAccountRegistry.verifyAccountOwner(account, sender) ||\\n externalAccountRegistry.verifyAccountOwner(account, sender),\\n \\\"Gateway: sender is not the account owner\\\"\\n );\\n }\\n\\n bool succeeded;\\n\\n for (uint256 i = 0; i < data.length; i++) {\\n require(\\n to[i] != address(0),\\n \\\"Gateway: cannot send to 0x0\\\"\\n );\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender));\\n\\n require(\\n succeeded,\\n \\\"Gateway: batch transaction reverted\\\"\\n );\\n }\\n }\\n\\n // private functions (views)\\n\\n function _hashDelegatedBatch(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data\\n )\\n private\\n view\\n returns (bytes32)\\n {\\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked(\\n account,\\n nonce,\\n to,\\n _concatBytes(data)\\n ));\\n }\\n\\n function _hashDelegatedBatchWithGasPrice(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n uint256 gasPrice\\n )\\n private\\n view\\n returns (bytes32)\\n {\\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked(\\n account,\\n nonce,\\n to,\\n _concatBytes(data),\\n gasPrice\\n ));\\n }\\n\\n// private functions (pure)\\n\\n function _concatBytes(bytes[] memory data)\\n private\\n pure\\n returns (bytes memory)\\n {\\n bytes memory result;\\n uint dataLen = data.length;\\n\\n for (uint i = 0 ; i < dataLen ; i++) {\\n result = abi.encodePacked(result, data[i]);\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x666f10ebf96aef0a37607852871a6e1d816a271558b1dce43dda74fc73274ae4\",\"license\":\"MIT\"},\"src/gateway/GatewayRecipient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../common/libs/BytesLib.sol\\\";\\n\\n\\n/**\\n * @title Gateway recipient\\n *\\n * @notice Gateway target contract\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski \\n */\\ncontract GatewayRecipient {\\n using BytesLib for bytes;\\n\\n address public gateway;\\n\\n /**\\n * @dev internal constructor\\n */\\n constructor() internal {}\\n\\n // internal functions\\n\\n /**\\n * @notice Initializes `GatewayRecipient` contract\\n * @param gateway_ `Gateway` contract address\\n */\\n function _initializeGatewayRecipient(\\n address gateway_\\n )\\n internal\\n {\\n gateway = gateway_;\\n }\\n\\n // internal functions (views)\\n\\n /**\\n * @notice Gets gateway context account\\n * @return context account address\\n */\\n function _getContextAccount()\\n internal\\n view\\n returns (address)\\n {\\n return _getContextAddress(40);\\n }\\n\\n /**\\n * @notice Gets gateway context sender\\n * @return context sender address\\n */\\n function _getContextSender()\\n internal\\n view\\n returns (address)\\n {\\n return _getContextAddress(20);\\n }\\n\\n /**\\n * @notice Gets gateway context data\\n * @return context data\\n */\\n function _getContextData()\\n internal\\n view\\n returns (bytes calldata)\\n {\\n bytes calldata result;\\n\\n if (_isGatewaySender()) {\\n result = msg.data[:msg.data.length - 40];\\n } else {\\n result = msg.data;\\n }\\n\\n return result;\\n }\\n\\n // private functions (views)\\n\\n function _getContextAddress(\\n uint256 offset\\n )\\n private\\n view\\n returns (address)\\n {\\n address result = address(0);\\n\\n if (_isGatewaySender()) {\\n uint from = msg.data.length - offset;\\n result = bytes(msg.data[from:from + 20]).toAddress();\\n } else {\\n result = msg.sender;\\n }\\n\\n return result;\\n }\\n\\n function _isGatewaySender()\\n private\\n view\\n returns (bool)\\n {\\n bool result;\\n\\n if (msg.sender == gateway) {\\n require(\\n msg.data.length >= 44,\\n \\\"GatewayRecipient: invalid msg.data\\\"\\n );\\n\\n result = true;\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xe3fd29479d748d67360c61a9cbaafc66eaca25f476e59a45e842472bcf5233fc\",\"license\":\"MIT\"},\"src/personal/PersonalAccountRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../common/access/Guarded.sol\\\";\\nimport \\\"../common/account/AccountController.sol\\\";\\nimport \\\"../common/account/AccountRegistry.sol\\\";\\nimport \\\"../common/libs/BlockLib.sol\\\";\\nimport \\\"../common/libs/ECDSALib.sol\\\";\\nimport \\\"../common/libs/ECDSAExtendedLib.sol\\\";\\nimport \\\"../common/libs/SafeMathLib.sol\\\";\\nimport \\\"../common/lifecycle/Initializable.sol\\\";\\nimport \\\"../common/token/ERC20Token.sol\\\";\\nimport \\\"../gateway/GatewayRecipient.sol\\\";\\n\\n\\n/**\\n * @title Personal account registry\\n *\\n * @notice A registry for personal (controlled by owners) accounts\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski \\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}", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"batch\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"succeeded\",\"type\":\"bool\"}],\"name\":\"BatchDelegated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"}],\"name\":\"delegateBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"}],\"name\":\"delegateBatchWithGasPrice\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"batches\",\"type\":\"bytes[]\"},{\"internalType\":\"bool\",\"name\":\"revertOnFailure\",\"type\":\"bool\"}],\"name\":\"delegateBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"externalAccountRegistry\",\"outputs\":[{\"internalType\":\"contract ExternalAccountRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountNextNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"internalType\":\"struct Gateway.DelegatedBatch\",\"name\":\"delegatedBatch\",\"type\":\"tuple\"}],\"name\":\"hashDelegatedBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct Gateway.DelegatedBatchWithGasPrice\",\"name\":\"delegatedBatch\",\"type\":\"tuple\"}],\"name\":\"hashDelegatedBatchWithGasPrice\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ExternalAccountRegistry\",\"name\":\"externalAccountRegistry_\",\"type\":\"address\"},{\"internalType\":\"contract PersonalAccountRegistry\",\"name\":\"personalAccountRegistry_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"personalAccountRegistry\",\"outputs\":[{\"internalType\":\"contract PersonalAccountRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"to\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"sendBatchFromAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"events\":{\"BatchDelegated(address,bytes,bool)\":{\"details\":\"Emitted when the single batch is delegated\",\"params\":{\"batch\":\"batch\",\"sender\":\"sender address\",\"succeeded\":\"if succeeded\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"},\"delegateBatch(address,uint256,address[],bytes[],bytes)\":{\"details\":\"Use `hashDelegatedBatch` to create sender message payload. `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"nonce\":\"next account nonce\",\"senderSignature\":\"sender signature\",\"to\":\"array of batch recipients contracts\"}},\"delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)\":{\"details\":\"Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice) `GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return recovered address from `senderSignature` arg\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"nonce\":\"next account nonce\",\"senderSignature\":\"sender signature\",\"to\":\"array of batch recipients contracts\"}},\"delegateBatches(bytes[],bool)\":{\"details\":\"It will revert when all batches fail\",\"params\":{\"batches\":\"array of batches\",\"revertOnFailure\":\"reverts on any error\"}},\"getAccountNextNonce(address)\":{\"params\":{\"account\":\"account address\"},\"returns\":{\"_0\":\"next nonce\"}},\"hashDelegatedBatch((address,uint256,address[],bytes[]))\":{\"params\":{\"delegatedBatch\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))\":{\"params\":{\"delegatedBatch\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"initialize(address,address)\":{\"params\":{\"externalAccountRegistry_\":\"`ExternalAccountRegistry` contract address\",\"personalAccountRegistry_\":\"`PersonalAccountRegistry` contract address\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"sendBatch(address[],bytes[])\":{\"details\":\"`GatewayRecipient` context api: `_getContextAccount` will return `msg.sender` `_getContextSender` will return `msg.sender`\",\"params\":{\"data\":\"array of batch data\",\"to\":\"array of batch recipients contracts\"}},\"sendBatchFromAccount(address,address[],bytes[])\":{\"details\":\"`GatewayRecipient` context api: `_getContextAccount` will return `account` arg `_getContextSender` will return `msg.sender`\",\"params\":{\"account\":\"account address\",\"data\":\"array of batch data\",\"to\":\"array of batch recipients contracts\"}}},\"title\":\"Gateway\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"delegateBatch(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account\"},\"delegateBatchWithGasPrice(address,uint256,address[],bytes[],bytes)\":{\"notice\":\"Delegates batch from the account (with gas price)\"},\"delegateBatches(bytes[],bool)\":{\"notice\":\"Delegates multiple batches\"},\"getAccountNextNonce(address)\":{\"notice\":\"Gets next account nonce\"},\"hashDelegatedBatch((address,uint256,address[],bytes[]))\":{\"notice\":\"Hashes `DelegatedBatch` message payload\"},\"hashDelegatedBatchWithGasPrice((address,uint256,address[],bytes[],uint256))\":{\"notice\":\"Hashes `DelegatedBatchWithGasPrice` message payload\"},\"initialize(address,address)\":{\"notice\":\"Initializes `Gateway` contract\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"sendBatch(address[],bytes[])\":{\"notice\":\"Sends batch\"},\"sendBatchFromAccount(address,address[],bytes[])\":{\"notice\":\"Sends batch from the account\"}},\"notice\":\"GSN replacement\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/gateway/Gateway.sol\":\"Gateway\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/common/access/Controlled.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\n/**\\n * @title Controlled\\n *\\n * @dev Contract module which provides an access control mechanism.\\n * It ensures there is only one controlling account of the smart contract\\n * and grants that account exclusive access to specific functions.\\n *\\n * The controller account will be the one that deploys the contract.\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski \\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/Gateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../common/libs/ECDSALib.sol\\\";\\nimport \\\"../common/libs/SafeMathLib.sol\\\";\\nimport \\\"../common/lifecycle/Initializable.sol\\\";\\nimport \\\"../common/signature/SignatureValidator.sol\\\";\\nimport \\\"../external/ExternalAccountRegistry.sol\\\";\\nimport \\\"../personal/PersonalAccountRegistry.sol\\\";\\n\\n\\n/**\\n * @title Gateway\\n *\\n * @notice GSN replacement\\n *\\n * @author Stanis\\u0142aw G\\u0142ogowski \\n */\\ncontract Gateway is Initializable, SignatureValidator {\\n using ECDSALib for bytes32;\\n using SafeMathLib for uint256;\\n\\n struct DelegatedBatch {\\n address account;\\n uint256 nonce;\\n address[] to;\\n bytes[] data;\\n }\\n\\n struct DelegatedBatchWithGasPrice {\\n address account;\\n uint256 nonce;\\n address[] to;\\n bytes[] data;\\n uint256 gasPrice;\\n }\\n\\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256(\\n \\\"DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)\\\"\\n );\\n\\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256(\\n \\\"DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)\\\"\\n );\\n\\n ExternalAccountRegistry public externalAccountRegistry;\\n PersonalAccountRegistry public personalAccountRegistry;\\n\\n mapping(address => uint256) private accountNonce;\\n\\n // events\\n\\n /**\\n * @dev Emitted when the single batch is delegated\\n * @param sender sender address\\n * @param batch batch\\n * @param succeeded if succeeded\\n */\\n event BatchDelegated(\\n address sender,\\n bytes batch,\\n bool succeeded\\n );\\n\\n /**\\n * @dev Public constructor\\n */\\n constructor() public Initializable() SignatureValidator() {}\\n\\n // external functions\\n\\n /**\\n * @notice Initializes `Gateway` contract\\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\\n */\\n function initialize(\\n ExternalAccountRegistry externalAccountRegistry_,\\n PersonalAccountRegistry personalAccountRegistry_\\n )\\n external\\n onlyInitializer\\n {\\n externalAccountRegistry = externalAccountRegistry_;\\n personalAccountRegistry = personalAccountRegistry_;\\n }\\n\\n // public functions\\n\\n /**\\n * @notice Sends batch\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `msg.sender`\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatch(\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n {\\n _sendBatch(\\n msg.sender,\\n msg.sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Sends batch from the account\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param account account address\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatchFromAccount(\\n address account,\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n {\\n _sendBatch(\\n account,\\n msg.sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates batch from the account\\n * @dev Use `hashDelegatedBatch` to create sender message payload.\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatch(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n {\\n require(\\n nonce > accountNonce[account],\\n \\\"Gateway: nonce is lower than current account nonce\\\"\\n );\\n\\n address sender = _hashDelegatedBatch(\\n account,\\n nonce,\\n to,\\n data\\n ).recoverAddress(senderSignature);\\n\\n accountNonce[account] = nonce;\\n\\n _sendBatch(\\n account,\\n sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates batch from the account (with gas price)\\n *\\n * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatchWithGasPrice(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n {\\n require(\\n nonce > accountNonce[account],\\n \\\"Gateway: nonce is lower than current account nonce\\\"\\n );\\n\\n address sender = _hashDelegatedBatchWithGasPrice(\\n account,\\n nonce,\\n to,\\n data,\\n tx.gasprice\\n ).recoverAddress(senderSignature);\\n\\n accountNonce[account] = nonce;\\n\\n _sendBatch(\\n account,\\n sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates multiple batches\\n * @dev It will revert when all batches fail\\n * @param batches array of batches\\n * @param revertOnFailure reverts on any error\\n */\\n function delegateBatches(\\n bytes[] memory batches,\\n bool revertOnFailure\\n )\\n public\\n {\\n require(\\n batches.length > 0,\\n \\\"Gateway: cannot delegate empty batches\\\"\\n );\\n\\n bool anySucceeded;\\n\\n for (uint256 i = 0; i < batches.length; i++) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool succeeded,) = address(this).call(batches[i]);\\n\\n if (revertOnFailure) {\\n require(\\n succeeded,\\n \\\"Gateway: batch reverted\\\"\\n );\\n } else if (succeeded && !anySucceeded) {\\n anySucceeded = true;\\n }\\n\\n emit BatchDelegated(\\n msg.sender,\\n batches[i],\\n succeeded\\n );\\n }\\n\\n if (!anySucceeded) {\\n revert(\\\"Gateway: all batches reverted\\\");\\n }\\n }\\n\\n // public functions (views)\\n\\n /**\\n * @notice Hashes `DelegatedBatch` message payload\\n * @param delegatedBatch struct\\n * @return hash\\n */\\n function hashDelegatedBatch(\\n DelegatedBatch memory delegatedBatch\\n )\\n public\\n view\\n returns (bytes32)\\n {\\n return _hashDelegatedBatch(\\n delegatedBatch.account,\\n delegatedBatch.nonce,\\n delegatedBatch.to,\\n delegatedBatch.data\\n );\\n }\\n\\n /**\\n * @notice Hashes `DelegatedBatchWithGasPrice` message payload\\n * @param delegatedBatch struct\\n * @return hash\\n */\\n function hashDelegatedBatchWithGasPrice(\\n DelegatedBatchWithGasPrice memory delegatedBatch\\n )\\n public\\n view\\n returns (bytes32)\\n {\\n return _hashDelegatedBatchWithGasPrice(\\n delegatedBatch.account,\\n delegatedBatch.nonce,\\n delegatedBatch.to,\\n delegatedBatch.data,\\n delegatedBatch.gasPrice\\n );\\n }\\n\\n // external functions (views)\\n\\n /**\\n * @notice Gets next account nonce\\n * @param account account address\\n * @return next nonce\\n */\\n function getAccountNextNonce(\\n address account\\n )\\n external\\n view\\n returns (uint256)\\n {\\n return accountNonce[account].add(1);\\n }\\n\\n // private functions\\n\\n function _sendBatch(\\n address account,\\n address sender,\\n address[] memory to,\\n bytes[] memory data\\n )\\n private\\n {\\n require(\\n account != address(0),\\n \\\"Gateway: cannot send from 0x0 account\\\"\\n );\\n require(\\n to.length > 0,\\n \\\"Gateway: cannot send empty batch\\\"\\n );\\n require(\\n data.length == to.length,\\n \\\"Gateway: invalid batch\\\"\\n );\\n\\n if (account != sender) {\\n require(\\n personalAccountRegistry.verifyAccountOwner(account, sender) ||\\n externalAccountRegistry.verifyAccountOwner(account, sender),\\n \\\"Gateway: sender is not the account owner\\\"\\n );\\n }\\n\\n bool succeeded;\\n\\n for (uint256 i = 0; i < data.length; i++) {\\n require(\\n to[i] != address(0),\\n \\\"Gateway: cannot send to 0x0\\\"\\n );\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender));\\n\\n require(\\n succeeded,\\n \\\"Gateway: batch transaction reverted\\\"\\n );\\n }\\n }\\n\\n // private functions (views)\\n\\n function _hashDelegatedBatch(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data\\n )\\n private\\n view\\n returns (bytes32)\\n {\\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked(\\n account,\\n nonce,\\n to,\\n _concatBytes(data)\\n ));\\n }\\n\\n function _hashDelegatedBatchWithGasPrice(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n uint256 gasPrice\\n )\\n private\\n view\\n returns (bytes32)\\n {\\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked(\\n account,\\n nonce,\\n to,\\n _concatBytes(data),\\n gasPrice\\n ));\\n }\\n\\n// private functions (pure)\\n\\n function _concatBytes(bytes[] memory data)\\n private\\n pure\\n returns (bytes memory)\\n {\\n bytes memory result;\\n uint dataLen = data.length;\\n\\n for (uint i = 0 ; i < dataLen ; i++) {\\n result = abi.encodePacked(result, data[i]);\\n }\\n\\n return result;\\n }\\n}\",\"keccak256\":\"0x41d4a32240b3f5e1279c39ec34e69455701b3ab20bc93e203a18ca83a29ccd51\",\"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/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": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600046905080600181905550506123f58061006d6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063867519c61161008c5780639f255626116100665780639f255626146101fe578063b5021b161461021a578063d2c83b9a14610236578063f92c5f7c14610254576100cf565b8063867519c6146101a657806387d31313146101c25780639a8a0592146101e0576100cf565b8063231badaf146100d4578063392e53cd146100f0578063485cc9551461010e5780635afaa7bb1461012a57806373e5a13f1461014657806376db2b4c14610176575b600080fd5b6100ee60048036038101906100e99190611438565b610284565b005b6100f861037f565b6040516101059190611e71565b60405180910390f35b610128600480360381019061012391906115e0565b6103d5565b005b610144600480360381019061013f9190611563565b610561565b005b610160600480360381019061015b919061165d565b610739565b60405161016d9190611e8c565b60405180910390f35b610190600480360381019061018b919061161c565b61075e565b60405161019d9190611e8c565b60405180910390f35b6101c060048036038101906101bb91906113b9565b610788565b005b6101ca610799565b6040516101d79190611f07565b60405180910390f35b6101e86107bf565b6040516101f591906120a2565b60405180910390f35b610218600480360381019061021391906114f7565b6107c5565b005b610234600480360381019061022f9190611438565b6107d5565b005b61023e6108d1565b60405161024b9190611eec565b60405180910390f35b61026e60048036038101906102699190611390565b6108f7565b60405161027b91906120a2565b60405180910390f35b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fc90611f82565b60405180910390fd5b60006103258261031788888888610953565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061037786828686610a71565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045a90611f42565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516105559190611def565b60405180910390a15050565b60008251116105a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059c90611fc2565b60405180910390fd5b600080600090505b83518110156106f35760003073ffffffffffffffffffffffffffffffffffffffff168583815181106105db57fe5b60200260200101516040516105f09190611d0b565b6000604051808303816000865af19150503d806000811461062d576040519150601f19603f3d011682016040523d82523d6000602084013e610632565b606091505b505090508315610681578061067c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067390611f62565b60405180910390fd5b610697565b80801561068c575082155b1561069657600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106106c557fe5b6020026020010151836040516106dd93929190611e0a565b60405180910390a15080806001019150506105ad565b5080610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072b90612082565b60405180910390fd5b505050565b60006107578260000151836020015184604001518560600151610953565b9050919050565b600061078182600001518360200151846040015185606001518660800151610edc565b9050919050565b61079483338484610a71565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b6107d133338484610a71565b5050565b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084d90611f82565b60405180910390fd5b600061087782610869888888883a610edc565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108c986828686610a71565b505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061094c6001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f4290919063ffffffff16565b9050919050565b60006109ac7f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661098587610f97565b6040516020016109989493929190611c6e565b604051602081830303815290604052610ffa565b9050949350505050565b60008060009050604183511415610a675760008060006020860151925060408601519150606086015160001a9050601b8160ff1610156109f757601b810190505b601b8160ff161480610a0c5750601c8160ff16145b15610a635760018782858560405160008152602001604052604051610a349493929190611ea7565b6020604051602081039080840390855afa158015610a56573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415610ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad890611fa2565b60405180910390fd5b6000825111610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c90612062565b60405180910390fd5b8151815114610b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6090612002565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610d3d57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610bf9929190611e48565b60206040518083038186803b158015610c1157600080fd5b505afa158015610c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4991906115b7565b80610cfd5750600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610cac929190611e48565b60206040518083038186803b158015610cc457600080fd5b505afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc91906115b7565b5b610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3390611fe2565b60405180910390fd5b5b600080600090505b8251811015610ed457600073ffffffffffffffffffffffffffffffffffffffff16848281518110610d7257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff161415610dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc890611f22565b60405180910390fd5b838181518110610ddd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16838281518110610e0757fe5b60200260200101518787604051602001610e2393929190611d22565b604051602081830303815290604052604051610e3f9190611d0b565b6000604051808303816000865af19150503d8060008114610e7c576040519150601f19603f3d011682016040523d82523d6000602084013e610e81565b606091505b50508092505081610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebe90612022565b60405180910390fd5b8080600101915050610d45565b505050505050565b6000610f377f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad878787610f0e88610f97565b87604051602001610f23959493929190611cb4565b604051602081830303815290604052610ffa565b905095945050505050565b600080828401905083811015610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490612042565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015610fef5782858281518110610fb857fe5b6020026020010151604051602001610fd1929190611d5b565b60405160208183030381529060405292508080600101915050610fa3565b508192505050919050565b60006110336001543085856040516020016110189493929190611da5565b6040516020818303038152906040528051906020012061103b565b905092915050565b60008160405160200161104e9190611d7f565b604051602081830303815290604052805190602001209050919050565b60008135905061107a81612375565b92915050565b600082601f83011261109157600080fd5b81356110a461109f826120ea565b6120bd565b915081818352602084019350602081019050838560208402820111156110c957600080fd5b60005b838110156110f957816110df888261106b565b8452602084019350602083019250506001810190506110cc565b5050505092915050565b600082601f83011261111457600080fd5b813561112761112282612112565b6120bd565b9150818183526020840193506020810190508360005b8381101561116d578135860161115388826111a1565b84526020840193506020830192505060018101905061113d565b5050505092915050565b6000813590506111868161238c565b92915050565b60008151905061119b8161238c565b92915050565b600082601f8301126111b257600080fd5b81356111c56111c08261213a565b6120bd565b915080825260208301602083018583830111156111e157600080fd5b6111ec8382846122dd565b50505092915050565b600081359050611204816123a3565b92915050565b600081359050611219816123ba565b92915050565b600060a0828403121561123157600080fd5b61123b60a06120bd565b9050600061124b8482850161106b565b600083015250602061125f8482850161137b565b602083015250604082013567ffffffffffffffff81111561127f57600080fd5b61128b84828501611080565b604083015250606082013567ffffffffffffffff8111156112ab57600080fd5b6112b784828501611103565b60608301525060806112cb8482850161137b565b60808301525092915050565b6000608082840312156112e957600080fd5b6112f360806120bd565b905060006113038482850161106b565b60008301525060206113178482850161137b565b602083015250604082013567ffffffffffffffff81111561133757600080fd5b61134384828501611080565b604083015250606082013567ffffffffffffffff81111561136357600080fd5b61136f84828501611103565b60608301525092915050565b60008135905061138a816123d1565b92915050565b6000602082840312156113a257600080fd5b60006113b08482850161106b565b91505092915050565b6000806000606084860312156113ce57600080fd5b60006113dc8682870161106b565b935050602084013567ffffffffffffffff8111156113f957600080fd5b61140586828701611080565b925050604084013567ffffffffffffffff81111561142257600080fd5b61142e86828701611103565b9150509250925092565b600080600080600060a0868803121561145057600080fd5b600061145e8882890161106b565b955050602061146f8882890161137b565b945050604086013567ffffffffffffffff81111561148c57600080fd5b61149888828901611080565b935050606086013567ffffffffffffffff8111156114b557600080fd5b6114c188828901611103565b925050608086013567ffffffffffffffff8111156114de57600080fd5b6114ea888289016111a1565b9150509295509295909350565b6000806040838503121561150a57600080fd5b600083013567ffffffffffffffff81111561152457600080fd5b61153085828601611080565b925050602083013567ffffffffffffffff81111561154d57600080fd5b61155985828601611103565b9150509250929050565b6000806040838503121561157657600080fd5b600083013567ffffffffffffffff81111561159057600080fd5b61159c85828601611103565b92505060206115ad85828601611177565b9150509250929050565b6000602082840312156115c957600080fd5b60006115d78482850161118c565b91505092915050565b600080604083850312156115f357600080fd5b6000611601858286016111f5565b92505060206116128582860161120a565b9150509250929050565b60006020828403121561162e57600080fd5b600082013567ffffffffffffffff81111561164857600080fd5b6116548482850161121f565b91505092915050565b60006020828403121561166f57600080fd5b600082013567ffffffffffffffff81111561168957600080fd5b611695848285016112d7565b91505092915050565b60006116aa83836116d4565b60208301905092915050565b6116bf8161225f565b82525050565b6116ce816121dc565b82525050565b6116dd816121dc565b82525050565b6116f46116ef826121dc565b61231f565b82525050565b600061170582612176565b61170f8185612199565b935061171a83612166565b8060005b8381101561174b578151611732888261169e565b975061173d8361218c565b92505060018101905061171e565b5085935050505092915050565b611761816121ee565b82525050565b611770816121fa565b82525050565b611787611782826121fa565b612331565b82525050565b600061179882612181565b6117a281856121a4565b93506117b28185602086016122ec565b6117bb81612357565b840191505092915050565b60006117d182612181565b6117db81856121b5565b93506117eb8185602086016122ec565b80840191505092915050565b61180081612271565b82525050565b61180f81612295565b82525050565b6000611822601b836121c0565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000611862601c836121d1565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006118a2602f836121c0565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006119086017836121c0565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006119486032836121c0565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b60006119ae6025836121c0565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a146026836121c0565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a7a6028836121c0565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ae06016836121c0565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000611b206023836121c0565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611b86601e836121c0565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000611bc66020836121c0565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b6000611c06601d836121c0565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b611c4281612248565b82525050565b611c59611c5482612248565b61234d565b82525050565b611c6881612252565b82525050565b6000611c7a82876116e3565b601482019150611c8a8286611c48565b602082019150611c9a82856116fa565b9150611ca682846117c6565b915081905095945050505050565b6000611cc082886116e3565b601482019150611cd08287611c48565b602082019150611ce082866116fa565b9150611cec82856117c6565b9150611cf88284611c48565b6020820191508190509695505050505050565b6000611d1782846117c6565b915081905092915050565b6000611d2e82866117c6565b9150611d3a82856116e3565b601482019150611d4a82846116e3565b601482019150819050949350505050565b6000611d6782856117c6565b9150611d7382846117c6565b91508190509392505050565b6000611d8a82611855565b9150611d968284611776565b60208201915081905092915050565b6000611db18287611c48565b602082019150611dc182866116e3565b601482019150611dd18285611776565b602082019150611de182846117c6565b915081905095945050505050565b6000602082019050611e0460008301846116b6565b92915050565b6000606082019050611e1f60008301866116b6565b8181036020830152611e31818561178d565b9050611e406040830184611758565b949350505050565b6000604082019050611e5d60008301856116c5565b611e6a60208301846116c5565b9392505050565b6000602082019050611e866000830184611758565b92915050565b6000602082019050611ea16000830184611767565b92915050565b6000608082019050611ebc6000830187611767565b611ec96020830186611c5f565b611ed66040830185611767565b611ee36060830184611767565b95945050505050565b6000602082019050611f0160008301846117f7565b92915050565b6000602082019050611f1c6000830184611806565b92915050565b60006020820190508181036000830152611f3b81611815565b9050919050565b60006020820190508181036000830152611f5b81611895565b9050919050565b60006020820190508181036000830152611f7b816118fb565b9050919050565b60006020820190508181036000830152611f9b8161193b565b9050919050565b60006020820190508181036000830152611fbb816119a1565b9050919050565b60006020820190508181036000830152611fdb81611a07565b9050919050565b60006020820190508181036000830152611ffb81611a6d565b9050919050565b6000602082019050818103600083015261201b81611ad3565b9050919050565b6000602082019050818103600083015261203b81611b13565b9050919050565b6000602082019050818103600083015261205b81611b79565b9050919050565b6000602082019050818103600083015261207b81611bb9565b9050919050565b6000602082019050818103600083015261209b81611bf9565b9050919050565b60006020820190506120b76000830184611c39565b92915050565b6000604051905081810181811067ffffffffffffffff821117156120e057600080fd5b8060405250919050565b600067ffffffffffffffff82111561210157600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561212957600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561215157600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006121e782612228565b9050919050565b60008115159050919050565b6000819050919050565b600061220f826121dc565b9050919050565b6000612221826121dc565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061226a826122b9565b9050919050565b600061227c82612283565b9050919050565b600061228e82612228565b9050919050565b60006122a0826122a7565b9050919050565b60006122b282612228565b9050919050565b60006122c4826122cb565b9050919050565b60006122d682612228565b9050919050565b82818337600083830152505050565b60005b8381101561230a5780820151818401526020810190506122ef565b83811115612319576000848401525b50505050565b600061232a8261233b565b9050919050565b6000819050919050565b600061234682612368565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61237e816121dc565b811461238957600080fd5b50565b612395816121ee565b81146123a057600080fd5b50565b6123ac81612204565b81146123b757600080fd5b50565b6123c381612216565b81146123ce57600080fd5b50565b6123da81612248565b81146123e557600080fd5b5056fea164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063867519c61161008c5780639f255626116100665780639f255626146101fe578063b5021b161461021a578063d2c83b9a14610236578063f92c5f7c14610254576100cf565b8063867519c6146101a657806387d31313146101c25780639a8a0592146101e0576100cf565b8063231badaf146100d4578063392e53cd146100f0578063485cc9551461010e5780635afaa7bb1461012a57806373e5a13f1461014657806376db2b4c14610176575b600080fd5b6100ee60048036038101906100e99190611438565b610284565b005b6100f861037f565b6040516101059190611e71565b60405180910390f35b610128600480360381019061012391906115e0565b6103d5565b005b610144600480360381019061013f9190611563565b610561565b005b610160600480360381019061015b919061165d565b610739565b60405161016d9190611e8c565b60405180910390f35b610190600480360381019061018b919061161c565b61075e565b60405161019d9190611e8c565b60405180910390f35b6101c060048036038101906101bb91906113b9565b610788565b005b6101ca610799565b6040516101d79190611f07565b60405180910390f35b6101e86107bf565b6040516101f591906120a2565b60405180910390f35b610218600480360381019061021391906114f7565b6107c5565b005b610234600480360381019061022f9190611438565b6107d5565b005b61023e6108d1565b60405161024b9190611eec565b60405180910390f35b61026e60048036038101906102699190611390565b6108f7565b60405161027b91906120a2565b60405180910390f35b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fc90611f82565b60405180910390fd5b60006103258261031788888888610953565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061037786828686610a71565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045a90611f42565b60405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516105559190611def565b60405180910390a15050565b60008251116105a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059c90611fc2565b60405180910390fd5b600080600090505b83518110156106f35760003073ffffffffffffffffffffffffffffffffffffffff168583815181106105db57fe5b60200260200101516040516105f09190611d0b565b6000604051808303816000865af19150503d806000811461062d576040519150601f19603f3d011682016040523d82523d6000602084013e610632565b606091505b505090508315610681578061067c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067390611f62565b60405180910390fd5b610697565b80801561068c575082155b1561069657600192505b5b7f361c14722cc344132c73396113f7164232448b09c544a149f09048648b43d872338684815181106106c557fe5b6020026020010151836040516106dd93929190611e0a565b60405180910390a15080806001019150506105ad565b5080610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072b90612082565b60405180910390fd5b505050565b60006107578260000151836020015184604001518560600151610953565b9050919050565b600061078182600001518360200151846040015185606001518660800151610edc565b9050919050565b61079483338484610a71565b505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b6107d133338484610a71565b5050565b600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548411610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084d90611f82565b60405180910390fd5b600061087782610869888888883a610edc565b6109b690919063ffffffff16565b905084600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108c986828686610a71565b505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061094c6001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f4290919063ffffffff16565b9050919050565b60006109ac7f6848d0622081db2451400280dead7a739a080cb93852607c381af11e289769b286868661098587610f97565b6040516020016109989493929190611c6e565b604051602081830303815290604052610ffa565b9050949350505050565b60008060009050604183511415610a675760008060006020860151925060408601519150606086015160001a9050601b8160ff1610156109f757601b810190505b601b8160ff161480610a0c5750601c8160ff16145b15610a635760018782858560405160008152602001604052604051610a349493929190611ea7565b6020604051602081039080840390855afa158015610a56573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415610ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad890611fa2565b60405180910390fd5b6000825111610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c90612062565b60405180910390fd5b8151815114610b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6090612002565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610d3d57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610bf9929190611e48565b60206040518083038186803b158015610c1157600080fd5b505afa158015610c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4991906115b7565b80610cfd5750600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bb890d3f85856040518363ffffffff1660e01b8152600401610cac929190611e48565b60206040518083038186803b158015610cc457600080fd5b505afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc91906115b7565b5b610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3390611fe2565b60405180910390fd5b5b600080600090505b8251811015610ed457600073ffffffffffffffffffffffffffffffffffffffff16848281518110610d7257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff161415610dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc890611f22565b60405180910390fd5b838181518110610ddd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16838281518110610e0757fe5b60200260200101518787604051602001610e2393929190611d22565b604051602081830303815290604052604051610e3f9190611d0b565b6000604051808303816000865af19150503d8060008114610e7c576040519150601f19603f3d011682016040523d82523d6000602084013e610e81565b606091505b50508092505081610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebe90612022565b60405180910390fd5b8080600101915050610d45565b505050505050565b6000610f377f6f4e1b2b1e5e49f4269e19e16e67a00cb0a796d96d30be3e4b540d3732e8bcad878787610f0e88610f97565b87604051602001610f23959493929190611cb4565b604051602081830303815290604052610ffa565b905095945050505050565b600080828401905083811015610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490612042565b60405180910390fd5b8091505092915050565b60608060008351905060005b81811015610fef5782858281518110610fb857fe5b6020026020010151604051602001610fd1929190611d5b565b60405160208183030381529060405292508080600101915050610fa3565b508192505050919050565b60006110336001543085856040516020016110189493929190611da5565b6040516020818303038152906040528051906020012061103b565b905092915050565b60008160405160200161104e9190611d7f565b604051602081830303815290604052805190602001209050919050565b60008135905061107a81612375565b92915050565b600082601f83011261109157600080fd5b81356110a461109f826120ea565b6120bd565b915081818352602084019350602081019050838560208402820111156110c957600080fd5b60005b838110156110f957816110df888261106b565b8452602084019350602083019250506001810190506110cc565b5050505092915050565b600082601f83011261111457600080fd5b813561112761112282612112565b6120bd565b9150818183526020840193506020810190508360005b8381101561116d578135860161115388826111a1565b84526020840193506020830192505060018101905061113d565b5050505092915050565b6000813590506111868161238c565b92915050565b60008151905061119b8161238c565b92915050565b600082601f8301126111b257600080fd5b81356111c56111c08261213a565b6120bd565b915080825260208301602083018583830111156111e157600080fd5b6111ec8382846122dd565b50505092915050565b600081359050611204816123a3565b92915050565b600081359050611219816123ba565b92915050565b600060a0828403121561123157600080fd5b61123b60a06120bd565b9050600061124b8482850161106b565b600083015250602061125f8482850161137b565b602083015250604082013567ffffffffffffffff81111561127f57600080fd5b61128b84828501611080565b604083015250606082013567ffffffffffffffff8111156112ab57600080fd5b6112b784828501611103565b60608301525060806112cb8482850161137b565b60808301525092915050565b6000608082840312156112e957600080fd5b6112f360806120bd565b905060006113038482850161106b565b60008301525060206113178482850161137b565b602083015250604082013567ffffffffffffffff81111561133757600080fd5b61134384828501611080565b604083015250606082013567ffffffffffffffff81111561136357600080fd5b61136f84828501611103565b60608301525092915050565b60008135905061138a816123d1565b92915050565b6000602082840312156113a257600080fd5b60006113b08482850161106b565b91505092915050565b6000806000606084860312156113ce57600080fd5b60006113dc8682870161106b565b935050602084013567ffffffffffffffff8111156113f957600080fd5b61140586828701611080565b925050604084013567ffffffffffffffff81111561142257600080fd5b61142e86828701611103565b9150509250925092565b600080600080600060a0868803121561145057600080fd5b600061145e8882890161106b565b955050602061146f8882890161137b565b945050604086013567ffffffffffffffff81111561148c57600080fd5b61149888828901611080565b935050606086013567ffffffffffffffff8111156114b557600080fd5b6114c188828901611103565b925050608086013567ffffffffffffffff8111156114de57600080fd5b6114ea888289016111a1565b9150509295509295909350565b6000806040838503121561150a57600080fd5b600083013567ffffffffffffffff81111561152457600080fd5b61153085828601611080565b925050602083013567ffffffffffffffff81111561154d57600080fd5b61155985828601611103565b9150509250929050565b6000806040838503121561157657600080fd5b600083013567ffffffffffffffff81111561159057600080fd5b61159c85828601611103565b92505060206115ad85828601611177565b9150509250929050565b6000602082840312156115c957600080fd5b60006115d78482850161118c565b91505092915050565b600080604083850312156115f357600080fd5b6000611601858286016111f5565b92505060206116128582860161120a565b9150509250929050565b60006020828403121561162e57600080fd5b600082013567ffffffffffffffff81111561164857600080fd5b6116548482850161121f565b91505092915050565b60006020828403121561166f57600080fd5b600082013567ffffffffffffffff81111561168957600080fd5b611695848285016112d7565b91505092915050565b60006116aa83836116d4565b60208301905092915050565b6116bf8161225f565b82525050565b6116ce816121dc565b82525050565b6116dd816121dc565b82525050565b6116f46116ef826121dc565b61231f565b82525050565b600061170582612176565b61170f8185612199565b935061171a83612166565b8060005b8381101561174b578151611732888261169e565b975061173d8361218c565b92505060018101905061171e565b5085935050505092915050565b611761816121ee565b82525050565b611770816121fa565b82525050565b611787611782826121fa565b612331565b82525050565b600061179882612181565b6117a281856121a4565b93506117b28185602086016122ec565b6117bb81612357565b840191505092915050565b60006117d182612181565b6117db81856121b5565b93506117eb8185602086016122ec565b80840191505092915050565b61180081612271565b82525050565b61180f81612295565b82525050565b6000611822601b836121c0565b91507f476174657761793a2063616e6e6f742073656e6420746f2030783000000000006000830152602082019050919050565b6000611862601c836121d1565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b60006118a2602f836121c0565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b60006119086017836121c0565b91507f476174657761793a2062617463682072657665727465640000000000000000006000830152602082019050919050565b60006119486032836121c0565b91507f476174657761793a206e6f6e6365206973206c6f776572207468616e2063757260008301527f72656e74206163636f756e74206e6f6e636500000000000000000000000000006020830152604082019050919050565b60006119ae6025836121c0565b91507f476174657761793a2063616e6e6f742073656e642066726f6d2030783020616360008301527f636f756e740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a146026836121c0565b91507f476174657761793a2063616e6e6f742064656c656761746520656d707479206260008301527f61746368657300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611a7a6028836121c0565b91507f476174657761793a2073656e646572206973206e6f7420746865206163636f7560008301527f6e74206f776e65720000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ae06016836121c0565b91507f476174657761793a20696e76616c6964206261746368000000000000000000006000830152602082019050919050565b6000611b206023836121c0565b91507f476174657761793a206261746368207472616e73616374696f6e20726576657260008301527f74656400000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611b86601e836121c0565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000611bc66020836121c0565b91507f476174657761793a2063616e6e6f742073656e6420656d7074792062617463686000830152602082019050919050565b6000611c06601d836121c0565b91507f476174657761793a20616c6c20626174636865732072657665727465640000006000830152602082019050919050565b611c4281612248565b82525050565b611c59611c5482612248565b61234d565b82525050565b611c6881612252565b82525050565b6000611c7a82876116e3565b601482019150611c8a8286611c48565b602082019150611c9a82856116fa565b9150611ca682846117c6565b915081905095945050505050565b6000611cc082886116e3565b601482019150611cd08287611c48565b602082019150611ce082866116fa565b9150611cec82856117c6565b9150611cf88284611c48565b6020820191508190509695505050505050565b6000611d1782846117c6565b915081905092915050565b6000611d2e82866117c6565b9150611d3a82856116e3565b601482019150611d4a82846116e3565b601482019150819050949350505050565b6000611d6782856117c6565b9150611d7382846117c6565b91508190509392505050565b6000611d8a82611855565b9150611d968284611776565b60208201915081905092915050565b6000611db18287611c48565b602082019150611dc182866116e3565b601482019150611dd18285611776565b602082019150611de182846117c6565b915081905095945050505050565b6000602082019050611e0460008301846116b6565b92915050565b6000606082019050611e1f60008301866116b6565b8181036020830152611e31818561178d565b9050611e406040830184611758565b949350505050565b6000604082019050611e5d60008301856116c5565b611e6a60208301846116c5565b9392505050565b6000602082019050611e866000830184611758565b92915050565b6000602082019050611ea16000830184611767565b92915050565b6000608082019050611ebc6000830187611767565b611ec96020830186611c5f565b611ed66040830185611767565b611ee36060830184611767565b95945050505050565b6000602082019050611f0160008301846117f7565b92915050565b6000602082019050611f1c6000830184611806565b92915050565b60006020820190508181036000830152611f3b81611815565b9050919050565b60006020820190508181036000830152611f5b81611895565b9050919050565b60006020820190508181036000830152611f7b816118fb565b9050919050565b60006020820190508181036000830152611f9b8161193b565b9050919050565b60006020820190508181036000830152611fbb816119a1565b9050919050565b60006020820190508181036000830152611fdb81611a07565b9050919050565b60006020820190508181036000830152611ffb81611a6d565b9050919050565b6000602082019050818103600083015261201b81611ad3565b9050919050565b6000602082019050818103600083015261203b81611b13565b9050919050565b6000602082019050818103600083015261205b81611b79565b9050919050565b6000602082019050818103600083015261207b81611bb9565b9050919050565b6000602082019050818103600083015261209b81611bf9565b9050919050565b60006020820190506120b76000830184611c39565b92915050565b6000604051905081810181811067ffffffffffffffff821117156120e057600080fd5b8060405250919050565b600067ffffffffffffffff82111561210157600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561212957600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561215157600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006121e782612228565b9050919050565b60008115159050919050565b6000819050919050565b600061220f826121dc565b9050919050565b6000612221826121dc565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061226a826122b9565b9050919050565b600061227c82612283565b9050919050565b600061228e82612228565b9050919050565b60006122a0826122a7565b9050919050565b60006122b282612228565b9050919050565b60006122c4826122cb565b9050919050565b60006122d682612228565b9050919050565b82818337600083830152505050565b60005b8381101561230a5780820151818401526020810190506122ef565b83811115612319576000848401525b50505050565b600061232a8261233b565b9050919050565b6000819050919050565b600061234682612368565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61237e816121dc565b811461238957600080fd5b50565b612395816121ee565b81146123a057600080fd5b50565b6123ac81612204565b81146123b757600080fd5b50565b6123c381612216565b81146123ce57600080fd5b50565b6123da81612248565b81146123e557600080fd5b5056fea164736f6c634300060c000a", "devdoc": { @@ -534,7 +534,7 @@ "label": "personalAccountRegistry", "offset": 0, "slot": "3", - "type": "t_contract(PersonalAccountRegistry)7452" + "type": "t_contract(PersonalAccountRegistry)8172" }, { "astId": 4653, @@ -556,7 +556,7 @@ "label": "contract ExternalAccountRegistry", "numberOfBytes": "20" }, - "t_contract(PersonalAccountRegistry)7452": { + "t_contract(PersonalAccountRegistry)8172": { "encoding": "inplace", "label": "contract PersonalAccountRegistry", "numberOfBytes": "20" diff --git a/deployments/neonDevnet/GatewayV2.json b/deployments/neonDevnet/GatewayV2.json new file mode 100644 index 00000000..f26f12a0 --- /dev/null +++ b/deployments/neonDevnet/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": "0xd47dd109531267312897c3af0f325133fa8b87204755426bb1559a721c72f183", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x53fE9288897e254698175740aa359E19E26c10af", + "contractAddress": null, + "transactionIndex": 0, + "gasUsed": "114631400", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbe280479829bdcac861a386ce8494476e192de2af181d5cb0fd41370c2dfb140", + "transactionHash": "0xd47dd109531267312897c3af0f325133fa8b87204755426bb1559a721c72f183", + "logs": [], + "blockNumber": 178555382, + "cumulativeGasUsed": "114631400", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", + "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\\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 \\\"../external/ExternalAccountRegistry.sol\\\";\\nimport \\\"../personal/PersonalAccountRegistry.sol\\\";\\n\\n/**\\n * @title Gateway V2 with guarded batching functions\\n *\\n * @notice GSN replacement\\n *\\n * @author Utkir Sobirov \\n */\\ncontract GatewayV2 is Initializable, SignatureValidator, Guarded {\\n using ECDSALib for bytes32;\\n using SafeMathLib for uint256;\\n\\n struct DelegatedBatch {\\n address account;\\n uint256 nonce;\\n address[] to;\\n bytes[] data;\\n }\\n\\n struct DelegatedBatchWithGasPrice {\\n address account;\\n uint256 nonce;\\n address[] to;\\n bytes[] data;\\n uint256 gasPrice;\\n }\\n\\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256(\\n \\\"DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)\\\"\\n );\\n\\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256(\\n \\\"DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)\\\"\\n );\\n\\n ExternalAccountRegistry public externalAccountRegistry;\\n PersonalAccountRegistry public personalAccountRegistry;\\n\\n mapping(address => uint256) private accountNonce;\\n\\n // events\\n\\n /**\\n * @dev Emitted when the single batch is delegated\\n * @param sender sender address\\n * @param batch batch\\n * @param succeeded if succeeded\\n */\\n event BatchDelegated(\\n address sender,\\n bytes batch,\\n bool succeeded\\n );\\n\\n /**\\n * @dev Public constructor\\n */\\n constructor() public Initializable() SignatureValidator() {}\\n\\n // external functions\\n\\n /**\\n * @notice Initializes `Gateway` contract\\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\\n */\\n function initialize(\\n ExternalAccountRegistry externalAccountRegistry_,\\n PersonalAccountRegistry personalAccountRegistry_\\n )\\n external\\n onlyInitializer\\n {\\n externalAccountRegistry = externalAccountRegistry_;\\n personalAccountRegistry = personalAccountRegistry_;\\n\\n address[] memory guardians;\\n _initializeGuarded(guardians); // adds tx.origin to guardians list\\n }\\n\\n // public functions\\n\\n /**\\n * @notice Sends batch\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `msg.sender`\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatch(\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n {\\n _sendBatch(\\n msg.sender,\\n msg.sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Sends guarded batch\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `msg.sender`\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatchGuarded(\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n onlyGuardian\\n {\\n sendBatch(to, data);\\n }\\n\\n /**\\n * @notice Sends batch from the account\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param account account address\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatchFromAccount(\\n address account,\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n {\\n _sendBatch(\\n account,\\n msg.sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Sends guarded batch from the account\\n * @dev `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return `msg.sender`\\n *\\n * @param account account address\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n */\\n function sendBatchFromAccountGuarded(\\n address account,\\n address[] memory to,\\n bytes[] memory data\\n )\\n public\\n onlyGuardian\\n {\\n sendBatchFromAccount(account, to, data);\\n }\\n\\n /**\\n * @notice Delegates batch from the account\\n * @dev Use `hashDelegatedBatch` to create sender message payload.\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatch(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n {\\n require(\\n nonce > accountNonce[account],\\n \\\"Gateway: nonce is lower than current account nonce\\\"\\n );\\n\\n address sender = _hashDelegatedBatch(\\n account,\\n nonce,\\n to,\\n data\\n ).recoverAddress(senderSignature);\\n\\n accountNonce[account] = nonce;\\n\\n _sendBatch(\\n account,\\n sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates guarded batch from the account\\n * @dev Use `hashDelegatedBatch` to create sender message payload.\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatchGuarded(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n onlyGuardian\\n {\\n delegateBatch(account, nonce, to, data, senderSignature);\\n }\\n\\n /**\\n * @notice Delegates batch from the account (with gas price)\\n *\\n * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatchWithGasPrice(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n {\\n require(\\n nonce > accountNonce[account],\\n \\\"Gateway: nonce is lower than current account nonce\\\"\\n );\\n\\n address sender = _hashDelegatedBatchWithGasPrice(\\n account,\\n nonce,\\n to,\\n data,\\n tx.gasprice\\n ).recoverAddress(senderSignature);\\n\\n accountNonce[account] = nonce;\\n\\n _sendBatch(\\n account,\\n sender,\\n to,\\n data\\n );\\n }\\n\\n /**\\n * @notice Delegates guarded batch from the account (with gas price)\\n *\\n * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\\n *\\n * `GatewayRecipient` context api:\\n * `_getContextAccount` will return `account` arg\\n * `_getContextSender` will return recovered address from `senderSignature` arg\\n *\\n * @param account account address\\n * @param nonce next account nonce\\n * @param to array of batch recipients contracts\\n * @param data array of batch data\\n * @param senderSignature sender signature\\n */\\n function delegateBatchWithGasPriceGuarded(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n bytes memory senderSignature\\n )\\n public\\n onlyGuardian\\n {\\n delegateBatchWithGasPrice(account, nonce, to, data, senderSignature);\\n }\\n\\n /**\\n * @notice Delegates multiple batches\\n * @dev It will revert when all batches fail\\n * @param batches array of batches\\n * @param revertOnFailure reverts on any error\\n */\\n function delegateBatches(\\n bytes[] memory batches,\\n bool revertOnFailure\\n )\\n public\\n {\\n require(\\n batches.length > 0,\\n \\\"Gateway: cannot delegate empty batches\\\"\\n );\\n\\n bool anySucceeded;\\n\\n for (uint256 i = 0; i < batches.length; i++) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool succeeded,) = address(this).call(batches[i]);\\n\\n if (revertOnFailure) {\\n require(\\n succeeded,\\n \\\"Gateway: batch reverted\\\"\\n );\\n } else if (succeeded && !anySucceeded) {\\n anySucceeded = true;\\n }\\n\\n emit BatchDelegated(\\n msg.sender,\\n batches[i],\\n succeeded\\n );\\n }\\n\\n if (!anySucceeded) {\\n revert(\\\"Gateway: all batches reverted\\\");\\n }\\n }\\n\\n /**\\n * @notice Delegates multiple guarded batches\\n * @dev It will revert when all batches fail\\n * @param batches array of batches\\n * @param revertOnFailure reverts on any error\\n */\\n function delegateBatchesGuarded(\\n bytes[] memory batches,\\n bool revertOnFailure\\n )\\n public\\n onlyGuardian\\n {\\n delegateBatches(batches, revertOnFailure);\\n }\\n\\n // public functions (views)\\n\\n /**\\n * @notice Hashes `DelegatedBatch` message payload\\n * @param delegatedBatch struct\\n * @return hash\\n */\\n function hashDelegatedBatch(\\n DelegatedBatch memory delegatedBatch\\n )\\n public\\n view\\n returns (bytes32)\\n {\\n return _hashDelegatedBatch(\\n delegatedBatch.account,\\n delegatedBatch.nonce,\\n delegatedBatch.to,\\n delegatedBatch.data\\n );\\n }\\n\\n /**\\n * @notice Hashes `DelegatedBatchWithGasPrice` message payload\\n * @param delegatedBatch struct\\n * @return hash\\n */\\n function hashDelegatedBatchWithGasPrice(\\n DelegatedBatchWithGasPrice memory delegatedBatch\\n )\\n public\\n view\\n returns (bytes32)\\n {\\n return _hashDelegatedBatchWithGasPrice(\\n delegatedBatch.account,\\n delegatedBatch.nonce,\\n delegatedBatch.to,\\n delegatedBatch.data,\\n delegatedBatch.gasPrice\\n );\\n }\\n\\n // external functions (views)\\n\\n /**\\n * @notice Gets next account nonce\\n * @param account account address\\n * @return next nonce\\n */\\n function getAccountNextNonce(\\n address account\\n )\\n external\\n view\\n returns (uint256)\\n {\\n return accountNonce[account].add(1);\\n }\\n\\n // private functions\\n\\n function _sendBatch(\\n address account,\\n address sender,\\n address[] memory to,\\n bytes[] memory data\\n )\\n private\\n {\\n require(\\n account != address(0),\\n \\\"Gateway: cannot send from 0x0 account\\\"\\n );\\n require(\\n to.length > 0,\\n \\\"Gateway: cannot send empty batch\\\"\\n );\\n require(\\n data.length == to.length,\\n \\\"Gateway: invalid batch\\\"\\n );\\n\\n if (account != sender) {\\n require(\\n personalAccountRegistry.verifyAccountOwner(account, sender) ||\\n externalAccountRegistry.verifyAccountOwner(account, sender),\\n \\\"Gateway: sender is not the account owner\\\"\\n );\\n }\\n\\n bool succeeded;\\n\\n for (uint256 i = 0; i < data.length; i++) {\\n require(\\n to[i] != address(0),\\n \\\"Gateway: cannot send to 0x0\\\"\\n );\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender));\\n\\n require(\\n succeeded,\\n \\\"Gateway: batch transaction reverted\\\"\\n );\\n }\\n }\\n\\n // private functions (views)\\n\\n function _hashDelegatedBatch(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data\\n )\\n private\\n view\\n returns (bytes32)\\n {\\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked(\\n account,\\n nonce,\\n to,\\n _concatBytes(data)\\n ));\\n }\\n\\n function _hashDelegatedBatchWithGasPrice(\\n address account,\\n uint256 nonce,\\n address[] memory to,\\n bytes[] memory data,\\n uint256 gasPrice\\n )\\n private\\n view\\n returns (bytes32)\\n {\\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked(\\n account,\\n nonce,\\n to,\\n _concatBytes(data),\\n gasPrice\\n ));\\n }\\n\\n// private functions (pure)\\n\\n function _concatBytes(bytes[] memory data)\\n private\\n pure\\n returns (bytes memory)\\n {\\n bytes memory result;\\n uint dataLen = data.length;\\n\\n for (uint i = 0 ; i < dataLen ; i++) {\\n result = abi.encodePacked(result, data[i]);\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x1721c8d16aaaf1ebde4eacf8f668a673ec80190769d85099d080840b4f4933a6\",\"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": 1871, + "contract": "src/gateway/GatewayV2.sol:GatewayV2", + "label": "initializer", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1935, + "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": 5408, + "contract": "src/gateway/GatewayV2.sol:GatewayV2", + "label": "externalAccountRegistry", + "offset": 0, + "slot": "3", + "type": "t_contract(ExternalAccountRegistry)4591" + }, + { + "astId": 5410, + "contract": "src/gateway/GatewayV2.sol:GatewayV2", + "label": "personalAccountRegistry", + "offset": 0, + "slot": "4", + "type": "t_contract(PersonalAccountRegistry)8172" + }, + { + "astId": 5414, + "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)4591": { + "encoding": "inplace", + "label": "contract ExternalAccountRegistry", + "numberOfBytes": "20" + }, + "t_contract(PersonalAccountRegistry)8172": { + "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/neonDevnet/PaymentRegistry.json b/deployments/neonDevnet/PaymentRegistry.json index 09385455..6d36506e 100644 --- a/deployments/neonDevnet/PaymentRegistry.json +++ b/deployments/neonDevnet/PaymentRegistry.json @@ -903,7 +903,7 @@ "type": "function" } ], - "transactionHash": "0x23514b60607e2f59c56170f5a4b9060b03c153224c94f0cd0332e08edf27e019", + "transactionHash": "0x87a6e9c662c740c36c83bd275c030f7de9f40bfeb9963a45a201bce5eb833ac3", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -911,16 +911,16 @@ "transactionIndex": 0, "gasUsed": "168172720", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2a24188a795303c179fa6d38a5927415949023466d11842fc17526702fd11fff", - "transactionHash": "0x23514b60607e2f59c56170f5a4b9060b03c153224c94f0cd0332e08edf27e019", + "blockHash": "0xdd689d0262769c7219cf281fa302bf197b457d3e56dd2fd3b38326769fbefa0d", + "transactionHash": "0x87a6e9c662c740c36c83bd275c030f7de9f40bfeb9963a45a201bce5eb833ac3", "logs": [], - "blockNumber": 173996887, + "blockNumber": 178555259, "cumulativeGasUsed": "168172720", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "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\":\"depositAccount\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"DepositAccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"depositAccount\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DepositExitCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"depositAccount\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"DepositExitRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"depositAccount\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"}],\"name\":\"DepositExitRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"depositAccount\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DepositWithdrawn\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PaymentChannelCommitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"channelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"PaymentDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"channelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalValue\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"depositValue\",\"type\":\"uint256\"}],\"name\":\"PaymentSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"channelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"PaymentWithdrawn\",\"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\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"guardianSignature\",\"type\":\"bytes\"}],\"name\":\"commitPaymentChannelAndDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"depositPaymentValue\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"guardianSignature\",\"type\":\"bytes\"}],\"name\":\"commitPaymentChannelAndSplit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"senderSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"guardianSignature\",\"type\":\"bytes\"}],\"name\":\"commitPaymentChannelAndWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"computeDepositAccountAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"computePaymentChannelHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"deployDepositAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositExitLockPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"externalAccountRegistry\",\"outputs\":[{\"internalType\":\"contract ExternalAccountRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getDepositExitLockedUntil\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getDepositWithdrawnAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPaymentChannelCommittedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PaymentRegistry.DepositWithdrawal\",\"name\":\"depositWithdrawal\",\"type\":\"tuple\"}],\"name\":\"hashDepositWithdrawal\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PaymentRegistry.PaymentChannelCommit\",\"name\":\"paymentChannelCommit\",\"type\":\"tuple\"}],\"name\":\"hashPaymentChannelCommit\",\"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\"},{\"internalType\":\"uint256\",\"name\":\"depositExitLockPeriod_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"guardians_\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"gateway_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"isDepositAccountDeployed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":\"token\",\"type\":\"address\"}],\"name\":\"processDepositExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"removeGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"requestDepositExit\",\"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\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"guardianSignature\",\"type\":\"bytes\"}],\"name\":\"withdrawDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"details\":\"the `DepositExit` process can be used in a case operator (guardian) couldn't sign commit / withdrawal message. Process will be rejected when any of senders channels will be committed.\",\"events\":{\"DepositAccountDeployed(address,address)\":{\"details\":\"Emitted when the deposit account is deployed\",\"params\":{\"depositAccount\":\"deposit account address\",\"owner\":\"owner address\"}},\"DepositExitCompleted(address,address,address,uint256)\":{\"details\":\"Emitted when the deposit exist is completed\",\"params\":{\"amount\":\"deposit exist amount\",\"depositAccount\":\"deposit account address\",\"owner\":\"owner address\",\"token\":\"token address\"}},\"DepositExitRejected(address,address,address)\":{\"details\":\"Emitted when the deposit exist is rejected\",\"params\":{\"depositAccount\":\"deposit account address\",\"owner\":\"owner address\",\"token\":\"token address\"}},\"DepositExitRequested(address,address,address,uint256)\":{\"details\":\"Emitted when the deposit exist is requested\",\"params\":{\"depositAccount\":\"deposit account address\",\"lockedUntil\":\"deposit exist locked util time\",\"owner\":\"owner address\",\"token\":\"token address\"}},\"DepositWithdrawn(address,address,address,uint256)\":{\"details\":\"Emitted when the deposit has been withdrawn\",\"params\":{\"amount\":\"withdrawn amount\",\"depositAccount\":\"deposit account address\",\"owner\":\"owner address\",\"token\":\"token address\"}},\"PaymentChannelCommitted(bytes32,address,address,address,bytes32,uint256)\":{\"details\":\"Emitted when the payment channel has been committed\",\"params\":{\"amount\":\"committed amount\",\"hash\":\"channel hash\",\"recipient\":\"recipient address\",\"sender\":\"sender address\",\"token\":\"token address\",\"uid\":\"unique channel id\"}},\"PaymentDeposited(bytes32,uint256)\":{\"details\":\"Emitted when the payment has been deposited\",\"params\":{\"channelHash\":\"channel hash\",\"value\":\"payment value\"}},\"PaymentSplit(bytes32,uint256,uint256)\":{\"details\":\"Emitted when the payment has been withdrawn and deposited (split)\",\"params\":{\"channelHash\":\"channel hash\",\"depositValue\":\"payment deposited value\",\"totalValue\":\"payment total value\"}},\"PaymentWithdrawn(bytes32,uint256)\":{\"details\":\"Emitted when the payment has been withdrawn\",\"params\":{\"channelHash\":\"channel hash\",\"value\":\"payment value\"}}},\"kind\":\"dev\",\"methods\":{\"addGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"commitPaymentChannelAndDeposit(address,address,bytes32,uint256,uint256,bytes,bytes)\":{\"params\":{\"amount\":\"amount to commit\",\"blockNumber\":\"block number\",\"guardianSignature\":\"guardian signature\",\"sender\":\"sender address\",\"senderSignature\":\"sender signature\",\"token\":\"token address\",\"uid\":\"unique channel id\"}},\"commitPaymentChannelAndSplit(address,address,bytes32,uint256,uint256,uint256,bytes,bytes)\":{\"params\":{\"amount\":\"amount to commit\",\"blockNumber\":\"block number\",\"depositPaymentValue\":\"amount to deposit\",\"guardianSignature\":\"guardian signature\",\"sender\":\"sender address\",\"senderSignature\":\"sender signature\",\"token\":\"token address\",\"uid\":\"unique channel id\"}},\"commitPaymentChannelAndWithdraw(address,address,bytes32,uint256,uint256,bytes,bytes)\":{\"params\":{\"amount\":\"amount to commit\",\"blockNumber\":\"block number\",\"guardianSignature\":\"guardian signature\",\"sender\":\"sender address\",\"senderSignature\":\"sender signature\",\"token\":\"token address\",\"uid\":\"unique channel id\"}},\"computeDepositAccountAddress(address)\":{\"params\":{\"owner\":\"owner address\"},\"returns\":{\"_0\":\"deposit account address\"}},\"computePaymentChannelHash(address,address,address,bytes32)\":{\"params\":{\"recipient\":\"recipient address\",\"sender\":\"sender address\",\"token\":\"token address\",\"uid\":\"unique channel id\"},\"returns\":{\"_0\":\"hash\"}},\"constructor\":{\"details\":\"Public constructor\"},\"deployDepositAccount(address)\":{\"params\":{\"owner\":\"owner address\"}},\"getDepositExitLockedUntil(address,address)\":{\"params\":{\"owner\":\"owner address\",\"token\":\"token address\"},\"returns\":{\"_0\":\"locked until time\"}},\"getDepositWithdrawnAmount(address,address)\":{\"params\":{\"owner\":\"owner address\",\"token\":\"token address\"},\"returns\":{\"_0\":\"withdrawn amount\"}},\"getPaymentChannelCommittedAmount(bytes32)\":{\"params\":{\"hash\":\"payment channel hash\"},\"returns\":{\"_0\":\"committed amount\"}},\"hashDepositWithdrawal((address,address,uint256))\":{\"params\":{\"depositWithdrawal\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"hashPaymentChannelCommit((address,address,address,bytes32,uint256,uint256))\":{\"params\":{\"paymentChannelCommit\":\"struct\"},\"returns\":{\"_0\":\"hash\"}},\"initialize(address,address,uint256,address[],address)\":{\"params\":{\"depositExitLockPeriod_\":\"deposit exit lock period\",\"externalAccountRegistry_\":\"`ExternalAccountRegistry` contract address\",\"gateway_\":\"`Gateway` contract address\",\"guardians_\":\"array of guardians addresses\",\"personalAccountRegistry_\":\"`PersonalAccountRegistry` contract address\"}},\"isDepositAccountDeployed(address)\":{\"params\":{\"owner\":\"owner address\"},\"returns\":{\"_0\":\"true when deposit account is deployed\"}},\"isGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"},\"returns\":{\"_0\":\"true when guardian exists\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"processDepositExit(address)\":{\"params\":{\"token\":\"token address\"}},\"removeGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"requestDepositExit(address)\":{\"params\":{\"token\":\"token address\"}},\"verifyGuardianSignature(bytes32,bytes)\":{\"params\":{\"messageHash\":\"message hash\",\"signature\":\"signature\"},\"returns\":{\"_0\":\"true on correct guardian signature\"}},\"withdrawDeposit(address,uint256,bytes)\":{\"params\":{\"amount\":\"amount to withdraw\",\"guardianSignature\":\"guardian signature\",\"token\":\"token address\"}}},\"title\":\"Payment registry\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addGuardian(address)\":{\"notice\":\"Adds a new guardian\"},\"commitPaymentChannelAndDeposit(address,address,bytes32,uint256,uint256,bytes,bytes)\":{\"notice\":\"Commits payment channel and deposit payment\"},\"commitPaymentChannelAndSplit(address,address,bytes32,uint256,uint256,uint256,bytes,bytes)\":{\"notice\":\"Commits payment channel, withdraws and deposits (split) payment\"},\"commitPaymentChannelAndWithdraw(address,address,bytes32,uint256,uint256,bytes,bytes)\":{\"notice\":\"Commits payment channel and withdraw payment\"},\"computeDepositAccountAddress(address)\":{\"notice\":\"Computes deposit account address\"},\"computePaymentChannelHash(address,address,address,bytes32)\":{\"notice\":\"Computes payment channel hash\"},\"deployDepositAccount(address)\":{\"notice\":\"Deploys deposit account\"},\"getDepositExitLockedUntil(address,address)\":{\"notice\":\"Gets deposit exit locked until time\"},\"getDepositWithdrawnAmount(address,address)\":{\"notice\":\"Gets deposit withdrawn amount\"},\"getPaymentChannelCommittedAmount(bytes32)\":{\"notice\":\"Gets payment channel committed amount\"},\"hashDepositWithdrawal((address,address,uint256))\":{\"notice\":\"Hashes `DepositWithdrawal` message payload\"},\"hashPaymentChannelCommit((address,address,address,bytes32,uint256,uint256))\":{\"notice\":\"Hashes `PaymentChannelCommit` message payload\"},\"initialize(address,address,uint256,address[],address)\":{\"notice\":\"Initialize `PaymentRegistry` contract\"},\"isDepositAccountDeployed(address)\":{\"notice\":\"Checks if deposit account is deployed\"},\"isGuardian(address)\":{\"notice\":\"Check if guardian exists\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"processDepositExit(address)\":{\"notice\":\"Processes deposit exit\"},\"removeGuardian(address)\":{\"notice\":\"Removes the existing guardian\"},\"requestDepositExit(address)\":{\"notice\":\"Requests deposit exit\"},\"verifyGuardianSignature(bytes32,bytes)\":{\"notice\":\"Verifies guardian signature\"},\"withdrawDeposit(address,uint256,bytes)\":{\"notice\":\"Withdraws deposit\"}},\"notice\":\"A registry for payment and payment channels\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/payments/PaymentRegistry.sol\":\"PaymentRegistry\"},\"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/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\\u0142aw G\\u0142ogowski \\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\",\"keccak256\":\"0xeac8f6b6b1cb749d72d8d5160a622fe4100a1e18a73635e51ce30e6f11029ad1\",\"license\":\"MIT\"},\"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\\u0142aw G\\u0142ogowski \\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\",\"keccak256\":\"0x84d3f908a35ba0f9dcc3e37808b42cdad0b81285ec006c96d25302d8dffa2704\",\"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": "0x608060405234801561001057600080fd5b5032600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060004690508060028190555050614c138061006e6000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639130c06e116100de578063c36326e711610097578063da1b213d11610071578063da1b213d146104bb578063dc7d6c31146104d7578063df04338014610507578063e0fe396e146105235761018e565b8063c36326e71461043d578063d0f710d61461046d578063d2c83b9a1461049d5761018e565b80639130c06e146103915780639a85fae2146103ad5780639a8a0592146103c9578063a526d83b146103e7578063b0274a7314610403578063bdff4b3b1461041f5761018e565b80636121fcfc1161014b578063714041561161012557806371404156146102f757806384389a2b1461031357806387d31313146103435780638a1773ab146103615761018e565b80636121fcfc1461028f5780636524a947146102bf5780636866da52146102db5761018e565b80630c68ba2114610193578063116191b6146101c35780632e4f161e146101e15780632e7037a014610211578063392e53cd1461024157806360bf4df21461025f575b600080fd5b6101ad60048036038101906101a89190612f83565b61053f565b6040516101ba91906140a9565b60405180910390f35b6101cb610594565b6040516101d89190613e92565b60405180910390f35b6101fb60048036038101906101f69190612fe8565b6105ba565b60405161020891906140c4565b60405180910390f35b61022b600480360381019061022691906133f5565b6105d2565b60405161023891906140c4565b60405180910390f35b6102496105f2565b60405161025691906140a9565b60405180910390f35b61027960048036038101906102749190612f83565b61064a565b6040516102869190613e92565b60405180910390f35b6102a960048036038101906102a49190612f83565b61065c565b6040516102b691906140a9565b60405180910390f35b6102d960048036038101906102d49190612f83565b6106f7565b005b6102f560048036038101906102f0919061320c565b610703565b005b610311600480360381019061030c9190612f83565b610a28565b005b61032d6004803603810190610328919061341e565b610c40565b60405161033a91906140c4565b60405180910390f35b61034b610c6f565b6040516103589190614200565b60405180910390f35b61037b600480360381019061037691906132a1565b610c95565b604051610388919061449d565b60405180910390f35b6103ab60048036038101906103a69190612f83565b610cb5565b005b6103c760048036038101906103c2919061304b565b610fe9565b005b6103d16110f4565b6040516103de919061449d565b60405180910390f35b61040160048036038101906103fc9190612f83565b6110fa565b005b61041d60048036038101906104189190612f83565b611191565b005b6104276113ac565b604051610434919061449d565b60405180910390f35b61045760048036038101906104529190612fac565b6113b2565b604051610464919061449d565b60405180910390f35b610487600480360381019061048291906132ca565b61143c565b60405161049491906140a9565b60405180910390f35b6104a5611495565b6040516104b291906141e5565b60405180910390f35b6104d560048036038101906104d09190613121565b6114bb565b005b6104f160048036038101906104ec9190612fac565b6115c2565b6040516104fe919061449d565b60405180910390f35b610521600480360381019061051c919061304b565b61164c565b005b61053d60048036038101906105389190613363565b61174f565b005b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006105c885858585611955565b9050949350505050565b60006105eb82600001518360200151846040015161198e565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b6000610655826119e6565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b61070081611a84565b50565b600061070d611c94565b905060006107a3600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205486611ca590919063ffffffff16565b9050600081116107e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107df9061435d565b60405180910390fd5b60006107f583888861198e565b90506108458186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cd2565b610884576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087b9061447d565b60405180910390fd5b85600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109128388611d3f565b610980600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848985611efc565b7f95f66b073d65f18e43f6b76c7ab8557787f5f766d86cab7c9c76f41be9f8abc6600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848989604051610a179493929190613f51565b60405180910390a150505050505050565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610ab3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aaa9061433d565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b199061443d565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba4906143dd565b60405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c35929190613ec8565b60405180910390a150565b6000610c68826000015183602001518460400151856060015186608001518760a0015161218c565b9050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060086000838152602001908152602001600020600001549050919050565b6000610cbf611c94565b90506000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811415610d89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d80906142fd565b60405180910390fd5b42811115610dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc39061437d565b60405180910390fd5b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415610f0d578173ffffffffffffffffffffffffffffffffffffffff16319050610f99565b8473ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401610f469190613e92565b60206040518083038186803b158015610f5e57600080fd5b505afa158015610f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f969190613447565b90505b610fa582858784611efc565b7f5300d9a2838baade7cdc628c82cb80c1298853ba5f389d51e2b47330336aeffc82858784604051610fda9493929190613f51565b60405180910390a15050505050565b6000610ff3611c94565b905060008060006110928d858e8e8e8e8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506121ed565b9250925092506110ac826110a5866119e6565b8e84611efc565b7f771bc0494e1a2fcbef19a8762845000d8c4500454c756a7370c955e39ed60fd483826040516110dd929190614140565b60405180910390a150505050505050505050505050565b60025481565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611185576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117c9061433d565b60405180910390fd5b61118e81612691565b50565b600061119b611c94565b90506000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114611264576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125b9061429d565b60405180910390fd5b61126d82611a84565b6112826006544261282090919063ffffffff16565b905080600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fed3c8c6cdfc6d7b91dc9db3e1f54866587c26c3c3e0f9e32cd1944974be43a50600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683858460405161139f9493929190613f51565b60405180910390a1505050565b60065481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600061148c8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cd2565b90509392505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006114c5611c94565b905060008060006115648e858f8f8f8f8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506121ed565b92509250925061157782858f848d612875565b7f8b67efde501ee9cd0e771f7436554c44a5c076239ff3a6fbb397646a4689c0f283828b6040516115aa93929190614169565b60405180910390a15050505050505050505050505050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000611656611c94565b905060008060006116f58d858e8e8e8e8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506121ed565b92509250925061170782858e84611efc565b7f6675346cd43846f7d47c310d39fb5c15bc7db66b3770338cdf1f133613a5ae988382604051611738929190614140565b60405180910390a150505050505050505050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146117df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117d69061427d565b60405180910390fd5b6000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008414156118bb576224ea006006819055506118c3565b836006819055505b61190d838380806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505061293a565b61191681612992565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516119459190613ead565b60405180910390a1505050505050565b60008484848460405160200161196e9493929190613cd9565b604051602081830303815290604052805190602001209050949350505050565b60006119dd7f3b3087c8f883f1f44cabe66444f5f9d96f69de6a88f364ea10959eef0331414a8585856040516020016119c993929190613d97565b6040516020818303038152906040526129d6565b90509392505050565b600080826040516020016119fa9190613cbe565b604051602081830303815290604052805190602001209050606060405180602001611a2490612cff565b6020820181038252601f19601f820116604052509050600060ff60f81b30848480519060200120604051602001611a5e9493929190613dd4565b6040516020818303038152906040528051906020012090508060001c9350505050919050565b600073ffffffffffffffffffffffffffffffffffffffff16600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611c9157600081604051602001611b2e9190613cbe565b60405160208183030381529060405280519060200120905080604051611b5390612cff565b8190604051809103906000f5905080158015611b73573d6000803e3d6000fd5b50600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fd80572c0f2f24f2d9d726d831bd860ed82b12bafaf01cfb6e4d38fb23c4347e9600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683604051611c87929190613ef1565b60405180910390a1505b50565b6000611ca06028612a17565b905090565b6000611cca8383604051806060016040528060218152602001614be660219139612aac565b905092915050565b600080611ce88385612b0190919063ffffffff16565b90506000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115611eee576000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fa19281a6f3163da06f6b82f3ecf0130493c52aba23cdc2a312f652742f0d1801600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168383604051611ee193929190613f1a565b60405180910390a1611ef8565b611ef782611a84565b5b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612016578373ffffffffffffffffffffffffffffffffffffffff16633f579f428483600067ffffffffffffffff81118015611f6757600080fd5b506040519080825280601f01601f191660200182016040528015611f9a5781602001600182028036833780820191505090505b506040518463ffffffff1660e01b8152600401611fb99392919061406b565b600060405180830381600087803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906120109190613322565b50612186565b60608473ffffffffffffffffffffffffffffffffffffffff16633f579f4284600063a9059cbb60e01b8887604051602401612052929190614042565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518463ffffffff1660e01b81526004016120cd93929190614004565b600060405180830381600087803b1580156120e757600080fd5b505af11580156120fb573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121249190613322565b905060008151111561218457808060200190518101906121449190613278565b612183576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217a9061431d565b60405180910390fd5b5b505b50505050565b60006121e17f745089e29f2abf28f618236a5dc04d214ac05ead3440ba532b69e9d160ba2e728888888888886040516020016121cd96959493929190613d27565b6040516020818303038152906040526129d6565b90509695505050505050565b6000806000806122018c8c8c8c8c8c61218c565b905060008651141561230057600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359b52ef88d838b6040518463ffffffff1660e01b815260040161226c93929190613fcd565b60206040518083038186803b15801561228457600080fd5b505afa158015612298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bc9190613278565b6122fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122f29061447d565b60405180910390fd5b6124f1565b60006123158783612b0190919063ffffffff16565b90508073ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff16146124ef57600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166334d323a48e838c6040518463ffffffff1660e01b81526004016123a993929190613f96565b60206040518083038186803b1580156123c157600080fd5b505afa1580156123d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f99190613278565b806124af5750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166334d323a48e838c6040518463ffffffff1660e01b815260040161245e93929190613f96565b60206040518083038186803b15801561247657600080fd5b505afa15801561248a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ae9190613278565b5b6124ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124e5906143bd565b60405180910390fd5b5b505b6124fb8186611cd2565b61253a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125319061447d565b60405180910390fd5b6125468c8c8c8c611955565b9350612571600860008681526020019081526020016000206000015488611ca590919063ffffffff16565b915060008214156125b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ae906142bd565b60405180910390fd5b8660086000868152602001908152602001600020600001819055506125dc8c8b611d3f565b600760008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692507f0d1cb77d1fe491f98926195d0b885509da18bc305dd1489f45610237d971ed46848d8d8d8d8c60405161267a969594939291906140df565b60405180910390a150985098509895505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612701576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f89061425d565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561278d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127849061441d565b60405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051612815929190613ec8565b60405180910390a150565b60008082840190508381101561286b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612862906143fd565b60405180910390fd5b8091505092915050565b600081116128b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128af9061423d565b60405180910390fd5b60006128cd8284611ca590919063ffffffff16565b905060008111612912576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129099061439d565b60405180910390fd5b61291e86868684611efc565b6129328661292b876119e6565b8685611efc565b505050505050565b6000815114156129525761294d32612691565b61298f565b60008151905060005b8181101561298c5761297f83828151811061297257fe5b6020026020010151612691565b808060010191505061295b565b50505b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000612a0f6002543085856040516020016129f49493929190613e48565b60405160208183030381529060405280519060200120612bbc565b905092915050565b60008060009050612a26612bec565b15612a9f576000836000369050039050612a9760003683906014850192612a4f9392919061455f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612c99565b915050612aa3565b3390505b80915050919050565b6000838311158290612af4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aeb919061421b565b60405180910390fd5b5082840390509392505050565b60008060009050604183511415612bb25760008060006020860151925060408601519150606086015160001a9050601b8160ff161015612b4257601b810190505b601b8160ff161480612b575750601c8160ff16145b15612bae5760018782858560405160008152602001604052604051612b7f94939291906141a0565b6020604051602081039080840390855afa158015612ba1573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600081604051602001612bcf9190613e22565b604051602081830303815290604052805190602001209050919050565b600080600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415612c9257602c60003690501015612c8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c84906142dd565b60405180910390fd5b600190505b8091505090565b6000806014835114612ce0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cd79061445d565b60405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b6103f7806147ef83390190565b600081359050612d1b81614764565b92915050565b60008083601f840112612d3357600080fd5b8235905067ffffffffffffffff811115612d4c57600080fd5b602083019150836020820283011115612d6457600080fd5b9250929050565b600081519050612d7a8161477b565b92915050565b600081359050612d8f81614792565b92915050565b60008083601f840112612da757600080fd5b8235905067ffffffffffffffff811115612dc057600080fd5b602083019150836001820283011115612dd857600080fd5b9250929050565b600082601f830112612df057600080fd5b8151612e03612dfe826144e5565b6144b8565b91508082526020830160208301858383011115612e1f57600080fd5b612e2a8382846146d1565b50505092915050565b600081359050612e42816147a9565b92915050565b600081359050612e57816147c0565b92915050565b600060608284031215612e6f57600080fd5b612e7960606144b8565b90506000612e8984828501612d0c565b6000830152506020612e9d84828501612d0c565b6020830152506040612eb184828501612f59565b60408301525092915050565b600060c08284031215612ecf57600080fd5b612ed960c06144b8565b90506000612ee984828501612d0c565b6000830152506020612efd84828501612d0c565b6020830152506040612f1184828501612d0c565b6040830152506060612f2584828501612d80565b6060830152506080612f3984828501612f59565b60808301525060a0612f4d84828501612f59565b60a08301525092915050565b600081359050612f68816147d7565b92915050565b600081519050612f7d816147d7565b92915050565b600060208284031215612f9557600080fd5b6000612fa384828501612d0c565b91505092915050565b60008060408385031215612fbf57600080fd5b6000612fcd85828601612d0c565b9250506020612fde85828601612d0c565b9150509250929050565b60008060008060808587031215612ffe57600080fd5b600061300c87828801612d0c565b945050602061301d87828801612d0c565b935050604061302e87828801612d0c565b925050606061303f87828801612d80565b91505092959194509250565b600080600080600080600080600060e08a8c03121561306957600080fd5b60006130778c828d01612d0c565b99505060206130888c828d01612d0c565b98505060406130998c828d01612d80565b97505060606130aa8c828d01612f59565b96505060806130bb8c828d01612f59565b95505060a08a013567ffffffffffffffff8111156130d857600080fd5b6130e48c828d01612d95565b945094505060c08a013567ffffffffffffffff81111561310357600080fd5b61310f8c828d01612d95565b92509250509295985092959850929598565b6000806000806000806000806000806101008b8d03121561314157600080fd5b600061314f8d828e01612d0c565b9a505060206131608d828e01612d0c565b99505060406131718d828e01612d80565b98505060606131828d828e01612f59565b97505060806131938d828e01612f59565b96505060a06131a48d828e01612f59565b95505060c08b013567ffffffffffffffff8111156131c157600080fd5b6131cd8d828e01612d95565b945094505060e08b013567ffffffffffffffff8111156131ec57600080fd5b6131f88d828e01612d95565b92509250509295989b9194979a5092959850565b6000806000806060858703121561322257600080fd5b600061323087828801612d0c565b945050602061324187828801612f59565b935050604085013567ffffffffffffffff81111561325e57600080fd5b61326a87828801612d95565b925092505092959194509250565b60006020828403121561328a57600080fd5b600061329884828501612d6b565b91505092915050565b6000602082840312156132b357600080fd5b60006132c184828501612d80565b91505092915050565b6000806000604084860312156132df57600080fd5b60006132ed86828701612d80565b935050602084013567ffffffffffffffff81111561330a57600080fd5b61331686828701612d95565b92509250509250925092565b60006020828403121561333457600080fd5b600082015167ffffffffffffffff81111561334e57600080fd5b61335a84828501612ddf565b91505092915050565b60008060008060008060a0878903121561337c57600080fd5b600061338a89828a01612e33565b965050602061339b89828a01612e48565b95505060406133ac89828a01612f59565b945050606087013567ffffffffffffffff8111156133c957600080fd5b6133d589828a01612d21565b935093505060806133e889828a01612d0c565b9150509295509295509295565b60006060828403121561340757600080fd5b600061341584828501612e5d565b91505092915050565b600060c0828403121561343057600080fd5b600061343e84828501612ebd565b91505092915050565b60006020828403121561345957600080fd5b600061346784828501612f6e565b91505092915050565b61347981614641565b82525050565b61348881614592565b82525050565b61349f61349a82614592565b614704565b82525050565b6134ae816145a4565b82525050565b6134c56134c0826145b0565b614716565b82525050565b6134d4816145dc565b82525050565b6134eb6134e6826145dc565b614720565b82525050565b60006134fc82614511565b6135068185614527565b93506135168185602086016146d1565b61351f81614746565b840191505092915050565b600061353582614511565b61353f8185614538565b935061354f8185602086016146d1565b80840191505092915050565b61356481614653565b82525050565b61357381614677565b82525050565b6135828161469b565b82525050565b60006135938261451c565b61359d8185614543565b93506135ad8185602086016146d1565b6135b681614746565b840191505092915050565b60006135ce602683614543565b91507f5061796d656e7452656769737472793a20696e76616c6964206465706f73697460008301527f2076616c756500000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613634601c83614554565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b6000613674602083614543565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b60006136b4602f83614543565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061371a602f83614543565b91507f5061796d656e7452656769737472793a206465706f736974206578697420616c60008301527f72656164792072657175657374656400000000000000000000000000000000006020830152604082019050919050565b6000613780602683614543565b91507f5061796d656e7452656769737472793a20696e76616c6964207061796d656e7460008301527f2076616c756500000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137e6602283614543565b91507f47617465776179526563697069656e743a20696e76616c6964206d73672e646160008301527f74610000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061384c602b83614543565b91507f5061796d656e7452656769737472793a206465706f7369742065786974206e6f60008301527f74207265717565737465640000000000000000000000000000000000000000006020830152604082019050919050565b60006138b2602d83614543565b91507f5061796d656e7452656769737472793a204552433230546f6b656e207472616e60008301527f73666572207265766572746564000000000000000000000000000000000000006020830152604082019050919050565b6000613918602683614543565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061397e601f83614543565b91507f5061796d656e7452656769737472793a20696e76616c696420616d6f756e74006000830152602082019050919050565b60006139be602483614543565b91507f5061796d656e7452656769737472793a206465706f7369742065786974206c6f60008301527f636b6564000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a24602783614543565b91507f5061796d656e7452656769737472793a20696e76616c6964207769746864726160008301527f772076616c7565000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a8a602983614543565b91507f5061796d656e7452656769737472793a20696e76616c69642073656e6465722060008301527f7369676e617475726500000000000000000000000000000000000000000000006020830152604082019050919050565b6000613af0601f83614543565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000613b30601e83614543565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000613b70602083614543565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b6000613bb0601b83614543565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b6000613bf0601d83614543565b91507f42797465734c69623a20696e76616c69642064617461206c656e6774680000006000830152602082019050919050565b6000613c30602b83614543565b91507f5061796d656e7452656769737472793a20696e76616c6964206775617264696160008301527f6e207369676e61747572650000000000000000000000000000000000000000006020830152604082019050919050565b613c928161462a565b82525050565b613ca9613ca48261462a565b61473c565b82525050565b613cb881614634565b82525050565b6000613cca828461348e565b60148201915081905092915050565b6000613ce5828761348e565b601482019150613cf5828661348e565b601482019150613d05828561348e565b601482019150613d1582846134da565b60208201915081905095945050505050565b6000613d33828961348e565b601482019150613d43828861348e565b601482019150613d53828761348e565b601482019150613d6382866134da565b602082019150613d738285613c98565b602082019150613d838284613c98565b602082019150819050979650505050505050565b6000613da3828661348e565b601482019150613db3828561348e565b601482019150613dc38284613c98565b602082019150819050949350505050565b6000613de082876134b4565b600182019150613df0828661348e565b601482019150613e0082856134da565b602082019150613e1082846134da565b60208201915081905095945050505050565b6000613e2d82613627565b9150613e3982846134da565b60208201915081905092915050565b6000613e548287613c98565b602082019150613e64828661348e565b601482019150613e7482856134da565b602082019150613e84828461352a565b915081905095945050505050565b6000602082019050613ea7600083018461347f565b92915050565b6000602082019050613ec26000830184613470565b92915050565b6000604082019050613edd6000830185613470565b613eea602083018461347f565b9392505050565b6000604082019050613f06600083018561347f565b613f13602083018461347f565b9392505050565b6000606082019050613f2f600083018661347f565b613f3c602083018561347f565b613f49604083018461347f565b949350505050565b6000608082019050613f66600083018761347f565b613f73602083018661347f565b613f80604083018561347f565b613f8d6060830184613c89565b95945050505050565b6000606082019050613fab600083018661347f565b613fb8602083018561347f565b613fc56040830184613c89565b949350505050565b6000606082019050613fe2600083018661347f565b613fef60208301856134cb565b613ffc6040830184613c89565b949350505050565b6000606082019050614019600083018661347f565b6140266020830185613579565b818103604083015261403881846134f1565b9050949350505050565b6000604082019050614057600083018561347f565b6140646020830184613c89565b9392505050565b6000606082019050614080600083018661347f565b61408d6020830185613c89565b818103604083015261409f81846134f1565b9050949350505050565b60006020820190506140be60008301846134a5565b92915050565b60006020820190506140d960008301846134cb565b92915050565b600060c0820190506140f460008301896134cb565b614101602083018861347f565b61410e604083018761347f565b61411b606083018661347f565b61412860808301856134cb565b61413560a0830184613c89565b979650505050505050565b600060408201905061415560008301856134cb565b6141626020830184613c89565b9392505050565b600060608201905061417e60008301866134cb565b61418b6020830185613c89565b6141986040830184613c89565b949350505050565b60006080820190506141b560008301876134cb565b6141c26020830186613caf565b6141cf60408301856134cb565b6141dc60608301846134cb565b95945050505050565b60006020820190506141fa600083018461355b565b92915050565b6000602082019050614215600083018461356a565b92915050565b600060208201905081810360008301526142358184613588565b905092915050565b60006020820190508181036000830152614256816135c1565b9050919050565b6000602082019050818103600083015261427681613667565b9050919050565b60006020820190508181036000830152614296816136a7565b9050919050565b600060208201905081810360008301526142b68161370d565b9050919050565b600060208201905081810360008301526142d681613773565b9050919050565b600060208201905081810360008301526142f6816137d9565b9050919050565b600060208201905081810360008301526143168161383f565b9050919050565b60006020820190508181036000830152614336816138a5565b9050919050565b600060208201905081810360008301526143568161390b565b9050919050565b6000602082019050818103600083015261437681613971565b9050919050565b60006020820190508181036000830152614396816139b1565b9050919050565b600060208201905081810360008301526143b681613a17565b9050919050565b600060208201905081810360008301526143d681613a7d565b9050919050565b600060208201905081810360008301526143f681613ae3565b9050919050565b6000602082019050818103600083015261441681613b23565b9050919050565b6000602082019050818103600083015261443681613b63565b9050919050565b6000602082019050818103600083015261445681613ba3565b9050919050565b6000602082019050818103600083015261447681613be3565b9050919050565b6000602082019050818103600083015261449681613c23565b9050919050565b60006020820190506144b26000830184613c89565b92915050565b6000604051905081810181811067ffffffffffffffff821117156144db57600080fd5b8060405250919050565b600067ffffffffffffffff8211156144fc57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000808585111561456f57600080fd5b8386111561457c57600080fd5b6001850283019150848603905094509492505050565b600061459d8261460a565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b60006145f182614592565b9050919050565b600061460382614592565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061464c826146ad565b9050919050565b600061465e82614665565b9050919050565b60006146708261460a565b9050919050565b600061468282614689565b9050919050565b60006146948261460a565b9050919050565b60006146a68261462a565b9050919050565b60006146b8826146bf565b9050919050565b60006146ca8261460a565b9050919050565b60005b838110156146ef5780820151818401526020810190506146d4565b838111156146fe576000848401525b50505050565b600061470f8261472a565b9050919050565b6000819050919050565b6000819050919050565b600061473582614757565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61476d81614592565b811461477857600080fd5b50565b614784816145a4565b811461478f57600080fd5b50565b61479b816145dc565b81146147a657600080fd5b50565b6147b2816145e6565b81146147bd57600080fd5b50565b6147c9816145f8565b81146147d457600080fd5b50565b6147e08161462a565b81146147eb57600080fd5b5056fe6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103a4806100536000396000f3fe60806040526004361061002d5760003560e01c80633f579f4214610039578063f77c47911461016257610034565b3661003457005b600080fd5b34801561004557600080fd5b506100e76004803603606081101561005c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156100a357600080fd5b8201836020820111156100b557600080fd5b803590602001918460018302840111640100000000831117156100d757600080fd5b90919293919293905050506101a3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561012757808201518184015260208101905061010c565b50505050905090810190601f1680156101545780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561016e57600080fd5b50610177610347565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610249576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061036c602c913960400191505060405180910390fd5b606060008673ffffffffffffffffffffffffffffffffffffffff1686868660405180838380828437808301925050509250505060006040518083038185875af1925050503d80600081146102b9576040519150601f19603f3d011682016040523d82523d6000602084013e6102be565b606091505b5080935081925050508061033a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4163636f756e743a207472616e73616374696f6e20726576657274656400000081525060200191505060405180910390fd5b8192505050949350505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fe436f6e74726f6c6c65643a206d73672e73656e646572206973206e6f742074686520636f6e74726f6c6c6572a164736f6c634300060c000a536166654d6174684c69623a207375627472616374696f6e206f766572666c6f77a164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80639130c06e116100de578063c36326e711610097578063da1b213d11610071578063da1b213d146104bb578063dc7d6c31146104d7578063df04338014610507578063e0fe396e146105235761018e565b8063c36326e71461043d578063d0f710d61461046d578063d2c83b9a1461049d5761018e565b80639130c06e146103915780639a85fae2146103ad5780639a8a0592146103c9578063a526d83b146103e7578063b0274a7314610403578063bdff4b3b1461041f5761018e565b80636121fcfc1161014b578063714041561161012557806371404156146102f757806384389a2b1461031357806387d31313146103435780638a1773ab146103615761018e565b80636121fcfc1461028f5780636524a947146102bf5780636866da52146102db5761018e565b80630c68ba2114610193578063116191b6146101c35780632e4f161e146101e15780632e7037a014610211578063392e53cd1461024157806360bf4df21461025f575b600080fd5b6101ad60048036038101906101a89190612f83565b61053f565b6040516101ba91906140a9565b60405180910390f35b6101cb610594565b6040516101d89190613e92565b60405180910390f35b6101fb60048036038101906101f69190612fe8565b6105ba565b60405161020891906140c4565b60405180910390f35b61022b600480360381019061022691906133f5565b6105d2565b60405161023891906140c4565b60405180910390f35b6102496105f2565b60405161025691906140a9565b60405180910390f35b61027960048036038101906102749190612f83565b61064a565b6040516102869190613e92565b60405180910390f35b6102a960048036038101906102a49190612f83565b61065c565b6040516102b691906140a9565b60405180910390f35b6102d960048036038101906102d49190612f83565b6106f7565b005b6102f560048036038101906102f0919061320c565b610703565b005b610311600480360381019061030c9190612f83565b610a28565b005b61032d6004803603810190610328919061341e565b610c40565b60405161033a91906140c4565b60405180910390f35b61034b610c6f565b6040516103589190614200565b60405180910390f35b61037b600480360381019061037691906132a1565b610c95565b604051610388919061449d565b60405180910390f35b6103ab60048036038101906103a69190612f83565b610cb5565b005b6103c760048036038101906103c2919061304b565b610fe9565b005b6103d16110f4565b6040516103de919061449d565b60405180910390f35b61040160048036038101906103fc9190612f83565b6110fa565b005b61041d60048036038101906104189190612f83565b611191565b005b6104276113ac565b604051610434919061449d565b60405180910390f35b61045760048036038101906104529190612fac565b6113b2565b604051610464919061449d565b60405180910390f35b610487600480360381019061048291906132ca565b61143c565b60405161049491906140a9565b60405180910390f35b6104a5611495565b6040516104b291906141e5565b60405180910390f35b6104d560048036038101906104d09190613121565b6114bb565b005b6104f160048036038101906104ec9190612fac565b6115c2565b6040516104fe919061449d565b60405180910390f35b610521600480360381019061051c919061304b565b61164c565b005b61053d60048036038101906105389190613363565b61174f565b005b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006105c885858585611955565b9050949350505050565b60006105eb82600001518360200151846040015161198e565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b6000610655826119e6565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b61070081611a84565b50565b600061070d611c94565b905060006107a3600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205486611ca590919063ffffffff16565b9050600081116107e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107df9061435d565b60405180910390fd5b60006107f583888861198e565b90506108458186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cd2565b610884576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087b9061447d565b60405180910390fd5b85600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109128388611d3f565b610980600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848985611efc565b7f95f66b073d65f18e43f6b76c7ab8557787f5f766d86cab7c9c76f41be9f8abc6600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848989604051610a179493929190613f51565b60405180910390a150505050505050565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610ab3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aaa9061433d565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161415610b22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b199061443d565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610bad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba4906143dd565b60405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051610c35929190613ec8565b60405180910390a150565b6000610c68826000015183602001518460400151856060015186608001518760a0015161218c565b9050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060086000838152602001908152602001600020600001549050919050565b6000610cbf611c94565b90506000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811415610d89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d80906142fd565b60405180910390fd5b42811115610dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc39061437d565b60405180910390fd5b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415610f0d578173ffffffffffffffffffffffffffffffffffffffff16319050610f99565b8473ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401610f469190613e92565b60206040518083038186803b158015610f5e57600080fd5b505afa158015610f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f969190613447565b90505b610fa582858784611efc565b7f5300d9a2838baade7cdc628c82cb80c1298853ba5f389d51e2b47330336aeffc82858784604051610fda9493929190613f51565b60405180910390a15050505050565b6000610ff3611c94565b905060008060006110928d858e8e8e8e8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506121ed565b9250925092506110ac826110a5866119e6565b8e84611efc565b7f771bc0494e1a2fcbef19a8762845000d8c4500454c756a7370c955e39ed60fd483826040516110dd929190614140565b60405180910390a150505050505050505050505050565b60025481565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611185576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117c9061433d565b60405180910390fd5b61118e81612691565b50565b600061119b611c94565b90506000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114611264576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125b9061429d565b60405180910390fd5b61126d82611a84565b6112826006544261282090919063ffffffff16565b905080600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fed3c8c6cdfc6d7b91dc9db3e1f54866587c26c3c3e0f9e32cd1944974be43a50600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683858460405161139f9493929190613f51565b60405180910390a1505050565b60065481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600061148c8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611cd2565b90509392505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006114c5611c94565b905060008060006115648e858f8f8f8f8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506121ed565b92509250925061157782858f848d612875565b7f8b67efde501ee9cd0e771f7436554c44a5c076239ff3a6fbb397646a4689c0f283828b6040516115aa93929190614169565b60405180910390a15050505050505050505050505050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000611656611c94565b905060008060006116f58d858e8e8e8e8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506121ed565b92509250925061170782858e84611efc565b7f6675346cd43846f7d47c310d39fb5c15bc7db66b3770338cdf1f133613a5ae988382604051611738929190614140565b60405180910390a150505050505050505050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146117df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117d69061427d565b60405180910390fd5b6000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008414156118bb576224ea006006819055506118c3565b836006819055505b61190d838380806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505061293a565b61191681612992565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6326040516119459190613ead565b60405180910390a1505050505050565b60008484848460405160200161196e9493929190613cd9565b604051602081830303815290604052805190602001209050949350505050565b60006119dd7f3b3087c8f883f1f44cabe66444f5f9d96f69de6a88f364ea10959eef0331414a8585856040516020016119c993929190613d97565b6040516020818303038152906040526129d6565b90509392505050565b600080826040516020016119fa9190613cbe565b604051602081830303815290604052805190602001209050606060405180602001611a2490612cff565b6020820181038252601f19601f820116604052509050600060ff60f81b30848480519060200120604051602001611a5e9493929190613dd4565b6040516020818303038152906040528051906020012090508060001c9350505050919050565b600073ffffffffffffffffffffffffffffffffffffffff16600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611c9157600081604051602001611b2e9190613cbe565b60405160208183030381529060405280519060200120905080604051611b5390612cff565b8190604051809103906000f5905080158015611b73573d6000803e3d6000fd5b50600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fd80572c0f2f24f2d9d726d831bd860ed82b12bafaf01cfb6e4d38fb23c4347e9600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683604051611c87929190613ef1565b60405180910390a1505b50565b6000611ca06028612a17565b905090565b6000611cca8383604051806060016040528060218152602001614be660219139612aac565b905092915050565b600080611ce88385612b0190919063ffffffff16565b90506000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115611eee576000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fa19281a6f3163da06f6b82f3ecf0130493c52aba23cdc2a312f652742f0d1801600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168383604051611ee193929190613f1a565b60405180910390a1611ef8565b611ef782611a84565b5b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612016578373ffffffffffffffffffffffffffffffffffffffff16633f579f428483600067ffffffffffffffff81118015611f6757600080fd5b506040519080825280601f01601f191660200182016040528015611f9a5781602001600182028036833780820191505090505b506040518463ffffffff1660e01b8152600401611fb99392919061406b565b600060405180830381600087803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906120109190613322565b50612186565b60608473ffffffffffffffffffffffffffffffffffffffff16633f579f4284600063a9059cbb60e01b8887604051602401612052929190614042565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518463ffffffff1660e01b81526004016120cd93929190614004565b600060405180830381600087803b1580156120e757600080fd5b505af11580156120fb573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121249190613322565b905060008151111561218457808060200190518101906121449190613278565b612183576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217a9061431d565b60405180910390fd5b5b505b50505050565b60006121e17f745089e29f2abf28f618236a5dc04d214ac05ead3440ba532b69e9d160ba2e728888888888886040516020016121cd96959493929190613d27565b6040516020818303038152906040526129d6565b90509695505050505050565b6000806000806122018c8c8c8c8c8c61218c565b905060008651141561230057600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359b52ef88d838b6040518463ffffffff1660e01b815260040161226c93929190613fcd565b60206040518083038186803b15801561228457600080fd5b505afa158015612298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bc9190613278565b6122fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122f29061447d565b60405180910390fd5b6124f1565b60006123158783612b0190919063ffffffff16565b90508073ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff16146124ef57600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166334d323a48e838c6040518463ffffffff1660e01b81526004016123a993929190613f96565b60206040518083038186803b1580156123c157600080fd5b505afa1580156123d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f99190613278565b806124af5750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166334d323a48e838c6040518463ffffffff1660e01b815260040161245e93929190613f96565b60206040518083038186803b15801561247657600080fd5b505afa15801561248a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ae9190613278565b5b6124ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124e5906143bd565b60405180910390fd5b5b505b6124fb8186611cd2565b61253a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125319061447d565b60405180910390fd5b6125468c8c8c8c611955565b9350612571600860008681526020019081526020016000206000015488611ca590919063ffffffff16565b915060008214156125b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ae906142bd565b60405180910390fd5b8660086000868152602001908152602001600020600001819055506125dc8c8b611d3f565b600760008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692507f0d1cb77d1fe491f98926195d0b885509da18bc305dd1489f45610237d971ed46848d8d8d8d8c60405161267a969594939291906140df565b60405180910390a150985098509895505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612701576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f89061425d565b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561278d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127849061441d565b60405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051612815929190613ec8565b60405180910390a150565b60008082840190508381101561286b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612862906143fd565b60405180910390fd5b8091505092915050565b600081116128b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128af9061423d565b60405180910390fd5b60006128cd8284611ca590919063ffffffff16565b905060008111612912576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129099061439d565b60405180910390fd5b61291e86868684611efc565b6129328661292b876119e6565b8685611efc565b505050505050565b6000815114156129525761294d32612691565b61298f565b60008151905060005b8181101561298c5761297f83828151811061297257fe5b6020026020010151612691565b808060010191505061295b565b50505b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000612a0f6002543085856040516020016129f49493929190613e48565b60405160208183030381529060405280519060200120612bbc565b905092915050565b60008060009050612a26612bec565b15612a9f576000836000369050039050612a9760003683906014850192612a4f9392919061455f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612c99565b915050612aa3565b3390505b80915050919050565b6000838311158290612af4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aeb919061421b565b60405180910390fd5b5082840390509392505050565b60008060009050604183511415612bb25760008060006020860151925060408601519150606086015160001a9050601b8160ff161015612b4257601b810190505b601b8160ff161480612b575750601c8160ff16145b15612bae5760018782858560405160008152602001604052604051612b7f94939291906141a0565b6020604051602081039080840390855afa158015612ba1573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600081604051602001612bcf9190613e22565b604051602081830303815290604052805190602001209050919050565b600080600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415612c9257602c60003690501015612c8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c84906142dd565b60405180910390fd5b600190505b8091505090565b6000806014835114612ce0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cd79061445d565b60405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b6103f7806147ef83390190565b600081359050612d1b81614764565b92915050565b60008083601f840112612d3357600080fd5b8235905067ffffffffffffffff811115612d4c57600080fd5b602083019150836020820283011115612d6457600080fd5b9250929050565b600081519050612d7a8161477b565b92915050565b600081359050612d8f81614792565b92915050565b60008083601f840112612da757600080fd5b8235905067ffffffffffffffff811115612dc057600080fd5b602083019150836001820283011115612dd857600080fd5b9250929050565b600082601f830112612df057600080fd5b8151612e03612dfe826144e5565b6144b8565b91508082526020830160208301858383011115612e1f57600080fd5b612e2a8382846146d1565b50505092915050565b600081359050612e42816147a9565b92915050565b600081359050612e57816147c0565b92915050565b600060608284031215612e6f57600080fd5b612e7960606144b8565b90506000612e8984828501612d0c565b6000830152506020612e9d84828501612d0c565b6020830152506040612eb184828501612f59565b60408301525092915050565b600060c08284031215612ecf57600080fd5b612ed960c06144b8565b90506000612ee984828501612d0c565b6000830152506020612efd84828501612d0c565b6020830152506040612f1184828501612d0c565b6040830152506060612f2584828501612d80565b6060830152506080612f3984828501612f59565b60808301525060a0612f4d84828501612f59565b60a08301525092915050565b600081359050612f68816147d7565b92915050565b600081519050612f7d816147d7565b92915050565b600060208284031215612f9557600080fd5b6000612fa384828501612d0c565b91505092915050565b60008060408385031215612fbf57600080fd5b6000612fcd85828601612d0c565b9250506020612fde85828601612d0c565b9150509250929050565b60008060008060808587031215612ffe57600080fd5b600061300c87828801612d0c565b945050602061301d87828801612d0c565b935050604061302e87828801612d0c565b925050606061303f87828801612d80565b91505092959194509250565b600080600080600080600080600060e08a8c03121561306957600080fd5b60006130778c828d01612d0c565b99505060206130888c828d01612d0c565b98505060406130998c828d01612d80565b97505060606130aa8c828d01612f59565b96505060806130bb8c828d01612f59565b95505060a08a013567ffffffffffffffff8111156130d857600080fd5b6130e48c828d01612d95565b945094505060c08a013567ffffffffffffffff81111561310357600080fd5b61310f8c828d01612d95565b92509250509295985092959850929598565b6000806000806000806000806000806101008b8d03121561314157600080fd5b600061314f8d828e01612d0c565b9a505060206131608d828e01612d0c565b99505060406131718d828e01612d80565b98505060606131828d828e01612f59565b97505060806131938d828e01612f59565b96505060a06131a48d828e01612f59565b95505060c08b013567ffffffffffffffff8111156131c157600080fd5b6131cd8d828e01612d95565b945094505060e08b013567ffffffffffffffff8111156131ec57600080fd5b6131f88d828e01612d95565b92509250509295989b9194979a5092959850565b6000806000806060858703121561322257600080fd5b600061323087828801612d0c565b945050602061324187828801612f59565b935050604085013567ffffffffffffffff81111561325e57600080fd5b61326a87828801612d95565b925092505092959194509250565b60006020828403121561328a57600080fd5b600061329884828501612d6b565b91505092915050565b6000602082840312156132b357600080fd5b60006132c184828501612d80565b91505092915050565b6000806000604084860312156132df57600080fd5b60006132ed86828701612d80565b935050602084013567ffffffffffffffff81111561330a57600080fd5b61331686828701612d95565b92509250509250925092565b60006020828403121561333457600080fd5b600082015167ffffffffffffffff81111561334e57600080fd5b61335a84828501612ddf565b91505092915050565b60008060008060008060a0878903121561337c57600080fd5b600061338a89828a01612e33565b965050602061339b89828a01612e48565b95505060406133ac89828a01612f59565b945050606087013567ffffffffffffffff8111156133c957600080fd5b6133d589828a01612d21565b935093505060806133e889828a01612d0c565b9150509295509295509295565b60006060828403121561340757600080fd5b600061341584828501612e5d565b91505092915050565b600060c0828403121561343057600080fd5b600061343e84828501612ebd565b91505092915050565b60006020828403121561345957600080fd5b600061346784828501612f6e565b91505092915050565b61347981614641565b82525050565b61348881614592565b82525050565b61349f61349a82614592565b614704565b82525050565b6134ae816145a4565b82525050565b6134c56134c0826145b0565b614716565b82525050565b6134d4816145dc565b82525050565b6134eb6134e6826145dc565b614720565b82525050565b60006134fc82614511565b6135068185614527565b93506135168185602086016146d1565b61351f81614746565b840191505092915050565b600061353582614511565b61353f8185614538565b935061354f8185602086016146d1565b80840191505092915050565b61356481614653565b82525050565b61357381614677565b82525050565b6135828161469b565b82525050565b60006135938261451c565b61359d8185614543565b93506135ad8185602086016146d1565b6135b681614746565b840191505092915050565b60006135ce602683614543565b91507f5061796d656e7452656769737472793a20696e76616c6964206465706f73697460008301527f2076616c756500000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613634601c83614554565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b6000613674602083614543565b91507f477561726465643a2063616e6e6f74206164642030783020677561726469616e6000830152602082019050919050565b60006136b4602f83614543565b91507f496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742060008301527f74686520696e697469616c697a657200000000000000000000000000000000006020830152604082019050919050565b600061371a602f83614543565b91507f5061796d656e7452656769737472793a206465706f736974206578697420616c60008301527f72656164792072657175657374656400000000000000000000000000000000006020830152604082019050919050565b6000613780602683614543565b91507f5061796d656e7452656769737472793a20696e76616c6964207061796d656e7460008301527f2076616c756500000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137e6602283614543565b91507f47617465776179526563697069656e743a20696e76616c6964206d73672e646160008301527f74610000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061384c602b83614543565b91507f5061796d656e7452656769737472793a206465706f7369742065786974206e6f60008301527f74207265717565737465640000000000000000000000000000000000000000006020830152604082019050919050565b60006138b2602d83614543565b91507f5061796d656e7452656769737472793a204552433230546f6b656e207472616e60008301527f73666572207265766572746564000000000000000000000000000000000000006020830152604082019050919050565b6000613918602683614543565b91507f477561726465643a2074782e6f726967696e206973206e6f742074686520677560008301527f61726469616e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061397e601f83614543565b91507f5061796d656e7452656769737472793a20696e76616c696420616d6f756e74006000830152602082019050919050565b60006139be602483614543565b91507f5061796d656e7452656769737472793a206465706f7369742065786974206c6f60008301527f636b6564000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a24602783614543565b91507f5061796d656e7452656769737472793a20696e76616c6964207769746864726160008301527f772076616c7565000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a8a602983614543565b91507f5061796d656e7452656769737472793a20696e76616c69642073656e6465722060008301527f7369676e617475726500000000000000000000000000000000000000000000006020830152604082019050919050565b6000613af0601f83614543565b91507f477561726465643a20677561726469616e20646f65736e2774206578697374006000830152602082019050919050565b6000613b30601e83614543565b91507f536166654d6174684c69623a206164646974696f6e206f766572666c6f7700006000830152602082019050919050565b6000613b70602083614543565b91507f477561726465643a20677561726469616e20616c7265616479206578697374736000830152602082019050919050565b6000613bb0601b83614543565b91507f477561726465643a2063616e6e6f742072656d6f76652073656c6600000000006000830152602082019050919050565b6000613bf0601d83614543565b91507f42797465734c69623a20696e76616c69642064617461206c656e6774680000006000830152602082019050919050565b6000613c30602b83614543565b91507f5061796d656e7452656769737472793a20696e76616c6964206775617264696160008301527f6e207369676e61747572650000000000000000000000000000000000000000006020830152604082019050919050565b613c928161462a565b82525050565b613ca9613ca48261462a565b61473c565b82525050565b613cb881614634565b82525050565b6000613cca828461348e565b60148201915081905092915050565b6000613ce5828761348e565b601482019150613cf5828661348e565b601482019150613d05828561348e565b601482019150613d1582846134da565b60208201915081905095945050505050565b6000613d33828961348e565b601482019150613d43828861348e565b601482019150613d53828761348e565b601482019150613d6382866134da565b602082019150613d738285613c98565b602082019150613d838284613c98565b602082019150819050979650505050505050565b6000613da3828661348e565b601482019150613db3828561348e565b601482019150613dc38284613c98565b602082019150819050949350505050565b6000613de082876134b4565b600182019150613df0828661348e565b601482019150613e0082856134da565b602082019150613e1082846134da565b60208201915081905095945050505050565b6000613e2d82613627565b9150613e3982846134da565b60208201915081905092915050565b6000613e548287613c98565b602082019150613e64828661348e565b601482019150613e7482856134da565b602082019150613e84828461352a565b915081905095945050505050565b6000602082019050613ea7600083018461347f565b92915050565b6000602082019050613ec26000830184613470565b92915050565b6000604082019050613edd6000830185613470565b613eea602083018461347f565b9392505050565b6000604082019050613f06600083018561347f565b613f13602083018461347f565b9392505050565b6000606082019050613f2f600083018661347f565b613f3c602083018561347f565b613f49604083018461347f565b949350505050565b6000608082019050613f66600083018761347f565b613f73602083018661347f565b613f80604083018561347f565b613f8d6060830184613c89565b95945050505050565b6000606082019050613fab600083018661347f565b613fb8602083018561347f565b613fc56040830184613c89565b949350505050565b6000606082019050613fe2600083018661347f565b613fef60208301856134cb565b613ffc6040830184613c89565b949350505050565b6000606082019050614019600083018661347f565b6140266020830185613579565b818103604083015261403881846134f1565b9050949350505050565b6000604082019050614057600083018561347f565b6140646020830184613c89565b9392505050565b6000606082019050614080600083018661347f565b61408d6020830185613c89565b818103604083015261409f81846134f1565b9050949350505050565b60006020820190506140be60008301846134a5565b92915050565b60006020820190506140d960008301846134cb565b92915050565b600060c0820190506140f460008301896134cb565b614101602083018861347f565b61410e604083018761347f565b61411b606083018661347f565b61412860808301856134cb565b61413560a0830184613c89565b979650505050505050565b600060408201905061415560008301856134cb565b6141626020830184613c89565b9392505050565b600060608201905061417e60008301866134cb565b61418b6020830185613c89565b6141986040830184613c89565b949350505050565b60006080820190506141b560008301876134cb565b6141c26020830186613caf565b6141cf60408301856134cb565b6141dc60608301846134cb565b95945050505050565b60006020820190506141fa600083018461355b565b92915050565b6000602082019050614215600083018461356a565b92915050565b600060208201905081810360008301526142358184613588565b905092915050565b60006020820190508181036000830152614256816135c1565b9050919050565b6000602082019050818103600083015261427681613667565b9050919050565b60006020820190508181036000830152614296816136a7565b9050919050565b600060208201905081810360008301526142b68161370d565b9050919050565b600060208201905081810360008301526142d681613773565b9050919050565b600060208201905081810360008301526142f6816137d9565b9050919050565b600060208201905081810360008301526143168161383f565b9050919050565b60006020820190508181036000830152614336816138a5565b9050919050565b600060208201905081810360008301526143568161390b565b9050919050565b6000602082019050818103600083015261437681613971565b9050919050565b60006020820190508181036000830152614396816139b1565b9050919050565b600060208201905081810360008301526143b681613a17565b9050919050565b600060208201905081810360008301526143d681613a7d565b9050919050565b600060208201905081810360008301526143f681613ae3565b9050919050565b6000602082019050818103600083015261441681613b23565b9050919050565b6000602082019050818103600083015261443681613b63565b9050919050565b6000602082019050818103600083015261445681613ba3565b9050919050565b6000602082019050818103600083015261447681613be3565b9050919050565b6000602082019050818103600083015261449681613c23565b9050919050565b60006020820190506144b26000830184613c89565b92915050565b6000604051905081810181811067ffffffffffffffff821117156144db57600080fd5b8060405250919050565b600067ffffffffffffffff8211156144fc57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000808585111561456f57600080fd5b8386111561457c57600080fd5b6001850283019150848603905094509492505050565b600061459d8261460a565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b60006145f182614592565b9050919050565b600061460382614592565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b600061464c826146ad565b9050919050565b600061465e82614665565b9050919050565b60006146708261460a565b9050919050565b600061468282614689565b9050919050565b60006146948261460a565b9050919050565b60006146a68261462a565b9050919050565b60006146b8826146bf565b9050919050565b60006146ca8261460a565b9050919050565b60005b838110156146ef5780820151818401526020810190506146d4565b838111156146fe576000848401525b50505050565b600061470f8261472a565b9050919050565b6000819050919050565b6000819050919050565b600061473582614757565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b61476d81614592565b811461477857600080fd5b50565b614784816145a4565b811461478f57600080fd5b50565b61479b816145dc565b81146147a657600080fd5b50565b6147b2816145e6565b81146147bd57600080fd5b50565b6147c9816145f8565b81146147d457600080fd5b50565b6147e08161462a565b81146147eb57600080fd5b5056fe6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103a4806100536000396000f3fe60806040526004361061002d5760003560e01c80633f579f4214610039578063f77c47911461016257610034565b3661003457005b600080fd5b34801561004557600080fd5b506100e76004803603606081101561005c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156100a357600080fd5b8201836020820111156100b557600080fd5b803590602001918460018302840111640100000000831117156100d757600080fd5b90919293919293905050506101a3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561012757808201518184015260208101905061010c565b50505050905090810190601f1680156101545780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561016e57600080fd5b50610177610347565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610249576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061036c602c913960400191505060405180910390fd5b606060008673ffffffffffffffffffffffffffffffffffffffff1686868660405180838380828437808301925050509250505060006040518083038185875af1925050503d80600081146102b9576040519150601f19603f3d011682016040523d82523d6000602084013e6102be565b606091505b5080935081925050508061033a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4163636f756e743a207472616e73616374696f6e20726576657274656400000081525060200191505060405180910390fd5b8192505050949350505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fe436f6e74726f6c6c65643a206d73672e73656e646572206973206e6f742074686520636f6e74726f6c6c6572a164736f6c634300060c000a536166654d6174684c69623a207375627472616374696f6e206f766572666c6f77a164736f6c634300060c000a", @@ -1284,7 +1284,7 @@ "type": "t_address" }, { - "astId": 5526, + "astId": 6246, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "externalAccountRegistry", "offset": 0, @@ -1292,15 +1292,15 @@ "type": "t_contract(ExternalAccountRegistry)4591" }, { - "astId": 5528, + "astId": 6248, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "personalAccountRegistry", "offset": 0, "slot": "5", - "type": "t_contract(PersonalAccountRegistry)7452" + "type": "t_contract(PersonalAccountRegistry)8172" }, { - "astId": 5530, + "astId": 6250, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "depositExitLockPeriod", "offset": 0, @@ -1308,20 +1308,20 @@ "type": "t_uint256" }, { - "astId": 5534, + "astId": 6254, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "deposits", "offset": 0, "slot": "7", - "type": "t_mapping(t_address,t_struct(Deposit)5488_storage)" + "type": "t_mapping(t_address,t_struct(Deposit)6208_storage)" }, { - "astId": 5538, + "astId": 6258, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "paymentChannels", "offset": 0, "slot": "8", - "type": "t_mapping(t_bytes32,t_struct(PaymentChannel)5491_storage)" + "type": "t_mapping(t_bytes32,t_struct(PaymentChannel)6211_storage)" } ], "types": { @@ -1345,7 +1345,7 @@ "label": "contract ExternalAccountRegistry", "numberOfBytes": "20" }, - "t_contract(PersonalAccountRegistry)7452": { + "t_contract(PersonalAccountRegistry)8172": { "encoding": "inplace", "label": "contract PersonalAccountRegistry", "numberOfBytes": "20" @@ -1357,12 +1357,12 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_address,t_struct(Deposit)5488_storage)": { + "t_mapping(t_address,t_struct(Deposit)6208_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct PaymentRegistry.Deposit)", "numberOfBytes": "32", - "value": "t_struct(Deposit)5488_storage" + "value": "t_struct(Deposit)6208_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -1371,19 +1371,19 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_mapping(t_bytes32,t_struct(PaymentChannel)5491_storage)": { + "t_mapping(t_bytes32,t_struct(PaymentChannel)6211_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct PaymentRegistry.PaymentChannel)", "numberOfBytes": "32", - "value": "t_struct(PaymentChannel)5491_storage" + "value": "t_struct(PaymentChannel)6211_storage" }, - "t_struct(Deposit)5488_storage": { + "t_struct(Deposit)6208_storage": { "encoding": "inplace", "label": "struct PaymentRegistry.Deposit", "members": [ { - "astId": 5479, + "astId": 6199, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "account", "offset": 0, @@ -1391,7 +1391,7 @@ "type": "t_address" }, { - "astId": 5483, + "astId": 6203, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "withdrawnAmount", "offset": 0, @@ -1399,7 +1399,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5487, + "astId": 6207, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "exitLockedUntil", "offset": 0, @@ -1409,12 +1409,12 @@ ], "numberOfBytes": "96" }, - "t_struct(PaymentChannel)5491_storage": { + "t_struct(PaymentChannel)6211_storage": { "encoding": "inplace", "label": "struct PaymentRegistry.PaymentChannel", "members": [ { - "astId": 5490, + "astId": 6210, "contract": "src/payments/PaymentRegistry.sol:PaymentRegistry", "label": "committedAmount", "offset": 0, diff --git a/deployments/neonDevnet/PersonalAccountImplementationV1.json b/deployments/neonDevnet/PersonalAccountImplementationV1.json index f0829ffc..b64211a5 100644 --- a/deployments/neonDevnet/PersonalAccountImplementationV1.json +++ b/deployments/neonDevnet/PersonalAccountImplementationV1.json @@ -242,24 +242,24 @@ "type": "function" } ], - "transactionHash": "0x620748c84602085f064e8d9453530f6425c1a27cc17c13c881d797735cd4573f", + "transactionHash": "0x9eac853d1f5dd68d67492171a94ac4807499e1b0310ce92f981052a1696eeb51", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", "contractAddress": null, - "transactionIndex": 0, + "transactionIndex": 1, "gasUsed": "41059200", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf35b1fad98c6553f07c0bd3b3c242c1745a13226a39f88b2ecadec5d7da22305", - "transactionHash": "0x620748c84602085f064e8d9453530f6425c1a27cc17c13c881d797735cd4573f", + "blockHash": "0x8cf18f2f98167999b9103ff58ec5fa96384b622c4f7ac6cab7e85e9197d6d759", + "transactionHash": "0x9eac853d1f5dd68d67492171a94ac4807499e1b0310ce92f981052a1696eeb51", "logs": [], - "blockNumber": 173996994, + "blockNumber": 178555304, "cumulativeGasUsed": "41059200", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "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\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"interfaceHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"canImplementInterfaceForAddress\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"registry_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"isValidSignature\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"isValidSignature\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"tokensReceived\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"},\"initialize(address)\":{\"params\":{\"registry_\":\"registry address\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}}},\"title\":\"Personal account implementation (version 1)\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(address)\":{\"notice\":\"Initializes `AccountImplementation` contract\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/personal/PersonalAccountImplementationV1.sol\":\"PersonalAccountImplementationV1\"},\"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/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/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\\u0142aw G\\u0142ogowski \\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\",\"keccak256\":\"0x7ec22f77f8e2c3059a9c728d463b1519f8d975b0d42d6a986cd45e22d62d59e8\",\"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/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/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\\u0142aw G\\u0142ogowski \\n */\\ncontract PersonalAccountImplementationV1 is AccountImplementationV1 {\\n\\n /**\\n * @dev Public constructor\\n */\\n constructor() public AccountImplementationV1() {}\\n}\\n\",\"keccak256\":\"0xd5a860c49ec0863366f4ecb583f87b48696e7edc3535e61f4b635a94b7255989\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610caa806100606000396000f3fe608060405234801561001057600080fd5b50600436106100925760003560e01c8063249cb3fa11610066578063249cb3fa1461047c578063392e53cd146104de5780637b103999146104fe578063c4d66de814610532578063f23a6e611461057657610092565b806223de2914610097578063150b7a02146101cf5780631626ba7e146102c557806320c13b0b1461037b575b600080fd5b6101cd600480360360c08110156100ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561013457600080fd5b82018360208201111561014657600080fd5b8035906020019184600183028401116401000000008311171561016857600080fd5b90919293919293908035906020019064010000000081111561018957600080fd5b82018360208201111561019b57600080fd5b803590602001918460018302840111640100000000831117156101bd57600080fd5b9091929391929390505050610676565b005b610290600480360360808110156101e557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561024c57600080fd5b82018360208201111561025e57600080fd5b8035906020019184600183028401116401000000008311171561028057600080fd5b9091929391929390505050610680565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b610346600480360360408110156102db57600080fd5b81019080803590602001909291908035906020019064010000000081111561030257600080fd5b82018360208201111561031457600080fd5b8035906020019184600183028401116401000000008311171561033657600080fd5b9091929391929390505050610695565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b6104476004803603604081101561039157600080fd5b81019080803590602001906401000000008111156103ae57600080fd5b8201836020820111156103c057600080fd5b803590602001918460018302840111640100000000831117156103e257600080fd5b90919293919293908035906020019064010000000081111561040357600080fd5b82018360208201111561041557600080fd5b8035906020019184600183028401116401000000008311171561043757600080fd5b90919293919293905050506107f9565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b6104c86004803603604081101561049257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061098a565b6040518082815260200191505060405180910390f35b6104e6610a66565b60405180821515815260200191505060405180910390f35b610506610abc565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6105746004803603602081101561054857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ae2565b005b610641600480360360a081101561058c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001906401000000008111156105fd57600080fd5b82018360208201111561060f57600080fd5b8035906020019184600183028401116401000000008311171561063157600080fd5b9091929391929390505050610c58565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b5050505050505050565b600063150b7a0260e01b905095945050505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1e382ce308686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060206040518083038186803b15801561075c57600080fd5b505afa158015610770573d6000803e3d6000fd5b505050506040513d602081101561078657600080fd5b81019080805190602001909291905050506107a85763ffffffff60e01b6107f0565b60405160200180807f697356616c69645369676e617475726528627974657333322c62797465732900815250601f019050604051602081830303815290604052805190602001205b90509392505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663124e9eb330878787876040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f82011690508083019250505097505050505050505060206040518083038186803b1580156108ec57600080fd5b505afa158015610900573d6000803e3d6000fd5b505050506040513d602081101561091657600080fd5b81019080805190602001909291905050506109385763ffffffff60e01b610980565b60405160200180807f697356616c69645369676e61747572652862797465732c627974657329000000815250601d019050604051602081830303815290604052805190602001205b9050949350505050565b60008060405160200180807f455243373737546f6b656e73526563697069656e74000000000000000000000081525060150190506040516020818303038152906040528051906020012084148015610a0d57503073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b15610a5c5760405160200180807f455243313832305f4143434550545f4d4147494300000000000000000000000081525060140190506040516020818303038152906040528051906020012090505b8091505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180610c6f602f913960400191505060405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600063f23a6e6160e01b9050969550505050505056fe496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a6572a164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100925760003560e01c8063249cb3fa11610066578063249cb3fa1461047c578063392e53cd146104de5780637b103999146104fe578063c4d66de814610532578063f23a6e611461057657610092565b806223de2914610097578063150b7a02146101cf5780631626ba7e146102c557806320c13b0b1461037b575b600080fd5b6101cd600480360360c08110156100ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561013457600080fd5b82018360208201111561014657600080fd5b8035906020019184600183028401116401000000008311171561016857600080fd5b90919293919293908035906020019064010000000081111561018957600080fd5b82018360208201111561019b57600080fd5b803590602001918460018302840111640100000000831117156101bd57600080fd5b9091929391929390505050610676565b005b610290600480360360808110156101e557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561024c57600080fd5b82018360208201111561025e57600080fd5b8035906020019184600183028401116401000000008311171561028057600080fd5b9091929391929390505050610680565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b610346600480360360408110156102db57600080fd5b81019080803590602001909291908035906020019064010000000081111561030257600080fd5b82018360208201111561031457600080fd5b8035906020019184600183028401116401000000008311171561033657600080fd5b9091929391929390505050610695565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b6104476004803603604081101561039157600080fd5b81019080803590602001906401000000008111156103ae57600080fd5b8201836020820111156103c057600080fd5b803590602001918460018302840111640100000000831117156103e257600080fd5b90919293919293908035906020019064010000000081111561040357600080fd5b82018360208201111561041557600080fd5b8035906020019184600183028401116401000000008311171561043757600080fd5b90919293919293905050506107f9565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b6104c86004803603604081101561049257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061098a565b6040518082815260200191505060405180910390f35b6104e6610a66565b60405180821515815260200191505060405180910390f35b610506610abc565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6105746004803603602081101561054857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ae2565b005b610641600480360360a081101561058c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001906401000000008111156105fd57600080fd5b82018360208201111561060f57600080fd5b8035906020019184600183028401116401000000008311171561063157600080fd5b9091929391929390505050610c58565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b5050505050505050565b600063150b7a0260e01b905095945050505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1e382ce308686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060206040518083038186803b15801561075c57600080fd5b505afa158015610770573d6000803e3d6000fd5b505050506040513d602081101561078657600080fd5b81019080805190602001909291905050506107a85763ffffffff60e01b6107f0565b60405160200180807f697356616c69645369676e617475726528627974657333322c62797465732900815250601f019050604051602081830303815290604052805190602001205b90509392505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663124e9eb330878787876040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f82011690508083019250505097505050505050505060206040518083038186803b1580156108ec57600080fd5b505afa158015610900573d6000803e3d6000fd5b505050506040513d602081101561091657600080fd5b81019080805190602001909291905050506109385763ffffffff60e01b610980565b60405160200180807f697356616c69645369676e61747572652862797465732c627974657329000000815250601d019050604051602081830303815290604052805190602001205b9050949350505050565b60008060405160200180807f455243373737546f6b656e73526563697069656e74000000000000000000000081525060150190506040516020818303038152906040528051906020012084148015610a0d57503073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b15610a5c5760405160200180807f455243313832305f4143434550545f4d4147494300000000000000000000000081525060140190506040516020818303038152906040528051906020012090505b8091505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180610c6f602f913960400191505060405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600063f23a6e6160e01b9050969550505050505056fe496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a6572a164736f6c634300060c000a", diff --git a/deployments/neonDevnet/PersonalAccountRegistry.json b/deployments/neonDevnet/PersonalAccountRegistry.json index b4892e13..051a0fff 100644 --- a/deployments/neonDevnet/PersonalAccountRegistry.json +++ b/deployments/neonDevnet/PersonalAccountRegistry.json @@ -647,7 +647,7 @@ "type": "function" } ], - "transactionHash": "0x2a0d6342070736407eb6a3ddf0775e9b7e4c8e67ca488916a7f6b88e195fa89c", + "transactionHash": "0x500168d580eb4a23db0cb3a14778177d89872e68bbaf74d21c0bb5424ba48ef9", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -655,16 +655,16 @@ "transactionIndex": 0, "gasUsed": "153626320", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1ca926a9db00fba71463b63e1748b309a6210d7bd2c63714cb442935fc9e4449", - "transactionHash": "0x2a0d6342070736407eb6a3ddf0775e9b7e4c8e67ca488916a7f6b88e195fa89c", + "blockHash": "0xbb09d64918928330766536127aca6387f5cae79f97cea1fd2ecbef8a6fb57c89", + "transactionHash": "0x500168d580eb4a23db0cb3a14778177d89872e68bbaf74d21c0bb5424ba48ef9", "logs": [], - "blockNumber": 173997006, + "blockNumber": 178555331, "cumulativeGasUsed": "153626320", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "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\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"AccountCallRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"accountImplementation\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"accountImplementation\",\"type\":\"address\"}],\"name\":\"AccountImplementationUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"AccountOwnerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"AccountOwnerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"accountRegistry\",\"type\":\"address\"}],\"name\":\"AccountRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"}],\"name\":\"AccountTransactionExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"accountImplementation\",\"type\":\"address\"}],\"name\":\"AccountUpgraded\",\"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\":[],\"name\":\"accountImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accountRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"addAccountOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"addGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"saltOwner\",\"type\":\"address\"}],\"name\":\"computeAccountAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"deployAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"executeAccountTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"guardians_\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"accountImplementation_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"gateway_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"isAccountDeployed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"isValidAccountSignature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"isValidAccountSignature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"refundAccountCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"removeAccountOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"removeGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accountImplementation_\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"upgradeAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"verifyAccountOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"verifyAccountOwnerAtBlock\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":\"Stanis\\u0142aw G\\u0142ogowski \",\"events\":{\"AccountCallRefunded(address,address,address,uint256)\":{\"details\":\"Emitted when the call is refunded\",\"params\":{\"account\":\"account address\",\"beneficiary\":\"beneficiary address\",\"token\":\"token address\",\"value\":\"value\"}},\"AccountOwnerAdded(address,address)\":{\"details\":\"Emitted when the new owner is added\",\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"}},\"AccountOwnerRemoved(address,address)\":{\"details\":\"Emitted when the existing owner is removed\",\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"}}},\"kind\":\"dev\",\"methods\":{\"addAccountOwner(address,address)\":{\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"}},\"addGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"computeAccountAddress(address)\":{\"params\":{\"saltOwner\":\"salt owner address\"},\"returns\":{\"_0\":\"account address\"}},\"constructor\":{\"details\":\"Public constructor\"},\"deployAccount(address)\":{\"params\":{\"account\":\"account address\"}},\"executeAccountTransaction(address,address,uint256,bytes)\":{\"details\":\"Deploys an account if not deployed yet\",\"params\":{\"account\":\"account address\",\"data\":\"data\",\"to\":\"to address\",\"value\":\"value\"}},\"initialize(address[],address,address)\":{\"params\":{\"accountImplementation_\":\"account implementation address\",\"gateway_\":\"`Gateway` contract address\",\"guardians_\":\"array of guardians addresses\"}},\"isAccountDeployed(address)\":{\"params\":{\"account\":\"account address\"},\"returns\":{\"_0\":\"true when account is deployed\"}},\"isGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"},\"returns\":{\"_0\":\"true when guardian exists\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"isValidAccountSignature(address,bytes,bytes)\":{\"params\":{\"account\":\"account address\",\"message\":\"message\",\"signature\":\"signature\"},\"returns\":{\"_0\":\"magic hash if valid\"}},\"isValidAccountSignature(address,bytes32,bytes)\":{\"params\":{\"account\":\"account address\",\"messageHash\":\"message hash\",\"signature\":\"signature\"},\"returns\":{\"_0\":\"magic hash if valid\"}},\"refundAccountCall(address,address,uint256)\":{\"details\":\"Deploys an account if not deployed yet\",\"params\":{\"account\":\"account address\",\"token\":\"token address\",\"value\":\"value\"}},\"removeAccountOwner(address,address)\":{\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"}},\"removeGuardian(address)\":{\"params\":{\"guardian\":\"guardian address\"}},\"upgrade(address)\":{\"params\":{\"accountImplementation_\":\"account implementation address\"}},\"upgradeAccount(address)\":{\"params\":{\"account\":\"account address\"}},\"verifyAccountOwner(address,address)\":{\"params\":{\"account\":\"account address\",\"owner\":\"owner address\"},\"returns\":{\"_0\":\"true on correct account owner\"}},\"verifyAccountOwnerAtBlock(address,address,uint256)\":{\"params\":{\"account\":\"account address\",\"blockNumber\":\"block number to verify\",\"owner\":\"owner address\"},\"returns\":{\"_0\":\"true on correct account owner\"}},\"verifyGuardianSignature(bytes32,bytes)\":{\"params\":{\"messageHash\":\"message hash\",\"signature\":\"signature\"},\"returns\":{\"_0\":\"true on correct guardian signature\"}}},\"title\":\"Personal account registry\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addAccountOwner(address,address)\":{\"notice\":\"Adds a new account owner\"},\"addGuardian(address)\":{\"notice\":\"Adds a new guardian\"},\"computeAccountAddress(address)\":{\"notice\":\"Computes account address\"},\"deployAccount(address)\":{\"notice\":\"Deploys account\"},\"executeAccountTransaction(address,address,uint256,bytes)\":{\"notice\":\"Executes account transaction\"},\"initialize(address[],address,address)\":{\"notice\":\"Initializes `PersonalAccountRegistry` contract\"},\"isAccountDeployed(address)\":{\"notice\":\"Checks if account is deployed\"},\"isGuardian(address)\":{\"notice\":\"Check if guardian exists\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"isValidAccountSignature(address,bytes,bytes)\":{\"notice\":\"Verifies account signature\"},\"isValidAccountSignature(address,bytes32,bytes)\":{\"notice\":\"Verifies account signature\"},\"refundAccountCall(address,address,uint256)\":{\"notice\":\"Refunds account call\"},\"removeAccountOwner(address,address)\":{\"notice\":\"Removes the existing account owner\"},\"removeGuardian(address)\":{\"notice\":\"Removes the existing guardian\"},\"upgrade(address)\":{\"notice\":\"Upgrades `PersonalAccountRegistry` contract\"},\"upgradeAccount(address)\":{\"notice\":\"Upgrades account\"},\"verifyAccountOwner(address,address)\":{\"notice\":\"Verifies the owner of the account at the current block\"},\"verifyAccountOwnerAtBlock(address,address,uint256)\":{\"notice\":\"Verifies the owner of the account at a specific block\"},\"verifyGuardianSignature(bytes32,bytes)\":{\"notice\":\"Verifies guardian signature\"}},\"notice\":\"A registry for personal (controlled by owners) accounts\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/personal/PersonalAccountRegistry.sol\":\"PersonalAccountRegistry\"},\"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/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/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/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": "0x608060405234801561001057600080fd5b5032600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506144d1806100616000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806390482d72116100b8578063d0f710d61161007c578063d0f710d61461075e578063da9fc1ae146107f7578063db63f5821461083b578063e1e382ce1461089f578063e5c7278f14610958578063f4876c7414610a1b57610142565b806390482d7214610545578063a526d83b146105fe578063bb890d3f14610642578063cade6a5d146106bc578063d089e11a1461072a57610142565b80631a8414031161010a5780631a841403146103515780633164b5e1146103bf57806334d323a414610419578063392e53cd1461049d57806343013c24146104bd578063714041561461050157610142565b80630900f010146101475780630c68ba211461018b57806311464fbe146101e5578063116191b614610219578063124e9eb31461024d575b600080fd5b6101896004803603602081101561015d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a7f565b005b6101cd600480360360208110156101a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b2e565b60405180821515815260200191505060405180910390f35b6101ed610b83565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610221610ba9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103396004803603606081101561026357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156102a057600080fd5b8201836020820111156102b257600080fd5b803590602001918460018302840111640100000000831117156102d457600080fd5b9091929391929390803590602001906401000000008111156102f557600080fd5b82018360208201111561030757600080fd5b8035906020019184600183028401116401000000008311171561032957600080fd5b9091929391929390505050610bcf565b60405180821515815260200191505060405180910390f35b6103bd6004803603606081101561036757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c88565b005b610401600480360360208110156103d557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ef3565b60405180821515815260200191505060405180910390f35b6104856004803603606081101561042f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f4c565b60405180821515815260200191505060405180910390f35b6104a561103a565b60405180821515815260200191505060405180910390f35b6104ff600480360360208110156104d357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611092565b005b6105436004803603602081101561051757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110aa565b005b6105fc6004803603606081101561055b57600080fd5b810190808035906020019064010000000081111561057857600080fd5b82018360208201111561058a57600080fd5b803590602001918460208302840111640100000000831117156105ac57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611370565b005b6106406004803603602081101561061457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611508565b005b6106a46004803603604081101561065857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115b5565b60405180821515815260200191505060405180910390f35b6106fe600480360360208110156106d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115c9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107326115db565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107df6004803603604081101561077457600080fd5b81019080803590602001909291908035906020019064010000000081111561079b57600080fd5b8201836020820111156107ad57600080fd5b803590602001918460018302840111640100000000831117156107cf57600080fd5b9091929391929390505050611601565b60405180821515815260200191505060405180910390f35b6108396004803603602081101561080d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061165a565b005b61089d6004803603604081101561085157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611670565b005b610940600480360360608110156108b557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156108fc57600080fd5b82018360208201111561090e57600080fd5b8035906020019184600183028401116401000000008311171561093057600080fd5b9091929391929390505050611905565b60405180821515815260200191505060405180910390f35b610a196004803603608081101561096e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109d557600080fd5b8201836020820111156109e757600080fd5b80359060200191846001830284011164010000000083111715610a0957600080fd5b9091929391929390505050611971565b005b610a7d60048036036040811015610a3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119de565b005b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610b20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143e46026913960400191505060405180910390fd5b610b2b816001611d0d565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610c7d86610c7885858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610c6a89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611e4e565b611fb790919063ffffffff16565b612087565b905095945050505050565b610c918361223e565b50610c9b83612685565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610d2f57610d29833283600067ffffffffffffffff81118015610cee57600080fd5b506040519080825280601f01601f191660200182016040528015610d215781602001600182028036833780820191505090505b506000612786565b50610e5d565b6060610dd38484600063a9059cbb60e01b3287604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506000612786565b9050600081511115610e5b57808060200190516020811015610df457600080fd5b8101908080519060200190929190505050610e5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061440a6035913960400191505060405180910390fd5b5b505b7feb5511fbef89123439f12682f0e9d0fc9696913b26eee55434c77d62c30aa7ca83328484604051808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060405180910390a1505050565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b60008060009050610f5d8585612087565b15610f6b576001905061102f565b61102c83600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050612c5490919063ffffffff16565b90505b809150509392505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b61109b8161223e565b506110a7816001612ca3565b50565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661114b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143e46026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614156111ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f477561726465643a2063616e6e6f742072656d6f76652073656c66000000000081525060200191505060405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166112ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f477561726465643a20677561726469616e20646f65736e27742065786973740081525060200191505060405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180614318602f913960400191505060405180910390fd5b6000600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506114a2848480806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050612f05565b6114ac3083612f5d565b6114b581612f77565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166115a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143e46026913960400191505060405180910390fd5b6115b281612fbb565b50565b60006115c18383612087565b905092915050565b60006115d4826131e2565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006116518484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613238565b90509392505050565b6116638161223e565b5061166d81612685565b50565b600061167b8361223e565b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806143b9602b913960400191505060405180910390fd5b6117b9600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff161515151581526020016001820154815250506132a5565b61180e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806142b7602c913960400191505060405180910390fd5b43600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f1ce3cbbc43ee231e5b950332f2b0b9dd7d349291a3ee411ce5c5c7ed745661bb8383604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050565b60006119678561196285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505087611fb790919063ffffffff16565b612087565b9050949350505050565b61197a8561223e565b5061198485612685565b6119d685858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506001612786565b505050505050565b6119e78261223e565b50600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180614498602d913960400191505060405180910390fd5b611b25600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff161515151581526020016001820154815250506132a5565b15611b7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061446b602d913960400191505060405180910390fd5b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055506000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f27e282f7712c5b4617277759c834b86d163dfc1aad25c8c3c5926a1c9e5644688282604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b81526020018061421e603b913960400191505060405180910390fd5b81600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508015611e4a577f70d9f5a076620216a6050e493f3ce69749de0b68fa4b839ba2518660ba8b9cf0600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5050565b6000611e5a82516132b8565b826040516020018082805190602001908083835b60208310611e915780518252602082019150602081019050602083039250611e6e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405260405160200180807f19457468657265756d205369676e6564204d6573736167653a0a000000000000815250601a0183805190602001908083835b60208310611f235780518252602082019150602081019050602083039250611f00565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b60208310611f745780518252602082019150602081019050602083039250611f51565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052805190602001209050919050565b6000806000905060418351141561207d5760008060006020860151925060408601519150606086015160001a9050601b8160ff161015611ff857601b810190505b601b8160ff16148061200d5750601c8160ff16145b156120795760018782858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561206c573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600080600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16156121ac576000600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154149050612234565b6000801b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154141561223357612202836131e2565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505b5b8091505092915050565b6000806122496133ff565b9050600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16156123c0576000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154146123bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001806142596038913960400191505060405180910390fd5b61267c565b6000801b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101541461245d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001806142596038913960400191505060405180910390fd5b600081604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b81526014019150506040516020818303038152906040528051906020012090506124aa81613410565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461252d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001806142596038913960400191505060405180910390fd5b80600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055507f27e282f7712c5b4617277759c834b86d163dfc1aad25c8c3c5926a1c9e5644688483604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505b80915050919050565b600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1661278357612726600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546001613606565b506001600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055505b50565b6060600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16141561280e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806143476025913960400191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415612893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061443f602c913960400191505060405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415612918576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806142916026913960400191505060405180910390fd5b60608673ffffffffffffffffffffffffffffffffffffffff16633f579f428787876040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156129aa57808201518184015260208101905061298f565b50505050905090810190601f1680156129d75780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156129f857600080fd5b505af1158015612a0c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015612a3657600080fd5b8101908080516040519392919084640100000000821115612a5657600080fd5b83820191506020820185811115612a6c57600080fd5b8251866001820283011164010000000082111715612a8957600080fd5b8083526020830192505050908051906020019080838360005b83811015612abd578082015181840152602081019050612aa2565b50505050905090810190601f168015612aea5780820380516001836020036101000a031916815260200191505b5060405250505090508215612c47577f99eeae1fb8801e2e878e060ec5e5b3557b3c4f8106e35d88cb573f293dae4e248787878785604051808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612ba1578082015181840152602081019050612b86565b50505050905090810190601f168015612bce5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015612c07578082015181840152602081019050612bec565b50505050905090810190601f168015612c345780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a15b8091505095945050505050565b60008060009050836000015115612c9957600084602001511415612c7b5760019050612c98565b6000831415612c8d5760019050612c97565b8284602001511190505b5b5b8091505092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d2257600080fd5b505afa158015612d36573d6000803e3d6000fd5b505050506040513d6020811015612d4c57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff161415612dca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061438e602b913960400191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663d784d426600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b158015612e5557600080fd5b505af1158015612e69573d6000803e3d6000fd5b505050508015612f01577feec27cdb8bd6f55c2c537deb52ab094a2437e85ef5197e6f064f90bff3ff563f82600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b5050565b600081511415612f1d57612f1832612fbb565b612f5a565b60008151905060005b81811015612f5757612f4a838281518110612f3d57fe5b6020026020010151612fbb565b8080600101915050612f26565b50505b50565b612f6882600061375a565b612f73816000611d0d565b5050565b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561305e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f477561726465643a2063616e6e6f74206164642030783020677561726469616e81525060200191505060405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561311d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f477561726465643a20677561726469616e20616c72656164792065786973747381525060200191505060405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b60008082604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b815260140191505060405160208183030381529060405280519060200120905061323081613410565b915050919050565b60008061324e8385611fb790919063ffffffff16565b90506000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b60006132b18243612c54565b9050919050565b60606000821415613300576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506133fa565b600082905060005b6000821461332a578080600101915050600a828161332257fe5b049150613308565b60608167ffffffffffffffff8111801561334357600080fd5b506040519080825280601f01601f1916602001820160405280156133765781602001600182028036833780820191505090505b50905060006001830390508593505b600084146133f257600a848161339757fe5b0660300160f81b828280600190039350815181106133b157fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84816133ea57fe5b049350613385565b819450505050505b919050565b600061340b601461389b565b905090565b600060606040518060200161342490613a8c565b6020820181038252601f19601f82011660405250600060a01b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600060a01b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516020018086805190602001908083835b602083106134be578051825260208201915060208101905060208303925061349b565b6001836020036101000a0380198251168184511680821785525050505050509050018573ffffffffffffffffffffffffffffffffffffffff19168152600c018473ffffffffffffffffffffffffffffffffffffffff1660601b81526014018373ffffffffffffffffffffffffffffffffffffffff19168152600c018273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401955050505050506040516020818303038152906040529050600060ff60f81b3085848051906020012060405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018473ffffffffffffffffffffffffffffffffffffffff1660601b81526014018381526020018281526020019450505050506040516020818303038152906040528051906020012090508060001c92505050919050565b60008083600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405161365c90613a8c565b808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff168152602001925050508190604051809103906000f59050801580156136b9573d6000803e3d6000fd5b5090508215613750577f2682a218602b9036c9869f006c5405ee4a1a65267653eb7e286123e5e1afde4c81600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156137e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260358152602001806142e36035913960400191505060405180910390fd5b81600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508015613897577f02e3c47057b8dc27a0929d3c394c314c73aa002d46939c31c9f71d1e77e86c10600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5050565b600080600090506138aa613930565b1561392357600083600036905003905061391b600036839060148501926138d393929190613a99565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506139f3565b915050613927565b3390505b80915050919050565b600080600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156139ec57602c600036905010156139e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061436c6022913960400191505060405180910390fd5b600190505b8091505090565b6000806014835114613a6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f42797465734c69623a20696e76616c69642064617461206c656e67746800000081525060200191505060405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b61075180613acd83390190565b60008085851115613aa957600080fd5b83861115613ab657600080fd5b600185028301915084860390509450949250505056fe608060405234801561001057600080fd5b506040516107513803806107518339818101604052604081101561003357600080fd5b810190808051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610630806101216000396000f3fe60806040526004361061004e5760003560e01c80633f579f42146100be5780635c60da1b146101e75780637b10399914610228578063d784d42614610269578063f77c4791146102ba57610055565b3661005557005b34801561006157600080fd5b50600080369050146100bc576000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050368060008037600080826000855af43d806000803e81600081146100b757816000f35b816000fd5b005b3480156100ca57600080fd5b5061016c600480360360608110156100e157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561012857600080fd5b82018360208201111561013a57600080fd5b8035906020019184600183028401116401000000008311171561015c57600080fd5b90919293919293905050506102fb565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101ac578082015181840152602081019050610191565b50505050905090810190601f1680156101d95780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101f357600080fd5b506101fc61049f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561023457600080fd5b5061023d6104c5565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561027557600080fd5b506102b86004803603602081101561028c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104eb565b005b3480156102c657600080fd5b506102cf6105d3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806105f8602c913960400191505060405180910390fd5b606060008673ffffffffffffffffffffffffffffffffffffffff1686868660405180838380828437808301925050509250505060006040518083038185875af1925050503d8060008114610411576040519150601f19603f3d011682016040523d82523d6000602084013e610416565b606091505b50809350819250505080610492576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4163636f756e743a207472616e73616374696f6e20726576657274656400000081525060200191505060405180910390fd5b8192505050949350505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461058f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806105f8602c913960400191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fe436f6e74726f6c6c65643a206d73672e73656e646572206973206e6f742074686520636f6e74726f6c6c6572a164736f6c634300060c000a4163636f756e74436f6e74726f6c6c65723a2063616e6e6f7420736574206163636f756e7420496d706c656d656e746174696f6e20746f20307830506572736f6e616c4163636f756e7452656769737472793a2073656e646572206973206e6f7420746865206163636f756e74206f776e65724163636f756e74436f6e74726f6c6c65723a2063616e6e6f742073656e6420746f2073656c66506572736f6e616c4163636f756e7452656769737472793a206f776e657220646f65736e27742065786973744163636f756e74436f6e74726f6c6c65723a2063616e6e6f7420736574206163636f756e7420726567697374727920746f20307830496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a65724163636f756e74436f6e74726f6c6c65723a2063616e6e6f742073656e6420746f2030783047617465776179526563697069656e743a20696e76616c6964206d73672e646174614163636f756e74436f6e74726f6c6c65723a206163636f756e7420616c7265616479207570677261646564506572736f6e616c4163636f756e7452656769737472793a2063616e6e6f742072656d6f76652073656c66477561726465643a2074782e6f726967696e206973206e6f742074686520677561726469616e506572736f6e616c4163636f756e7452656769737472793a204552433230546f6b656e207472616e736665722072657665727465644163636f756e74436f6e74726f6c6c65723a2063616e6e6f742073656e6420746f20636f6e74726f6c6c6572506572736f6e616c4163636f756e7452656769737472793a206f776e657220616c726561647920657869737473506572736f6e616c4163636f756e7452656769737472793a2063616e6e6f742061646420307830206f776e6572a164736f6c634300060c000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101425760003560e01c806390482d72116100b8578063d0f710d61161007c578063d0f710d61461075e578063da9fc1ae146107f7578063db63f5821461083b578063e1e382ce1461089f578063e5c7278f14610958578063f4876c7414610a1b57610142565b806390482d7214610545578063a526d83b146105fe578063bb890d3f14610642578063cade6a5d146106bc578063d089e11a1461072a57610142565b80631a8414031161010a5780631a841403146103515780633164b5e1146103bf57806334d323a414610419578063392e53cd1461049d57806343013c24146104bd578063714041561461050157610142565b80630900f010146101475780630c68ba211461018b57806311464fbe146101e5578063116191b614610219578063124e9eb31461024d575b600080fd5b6101896004803603602081101561015d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a7f565b005b6101cd600480360360208110156101a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b2e565b60405180821515815260200191505060405180910390f35b6101ed610b83565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610221610ba9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103396004803603606081101561026357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156102a057600080fd5b8201836020820111156102b257600080fd5b803590602001918460018302840111640100000000831117156102d457600080fd5b9091929391929390803590602001906401000000008111156102f557600080fd5b82018360208201111561030757600080fd5b8035906020019184600183028401116401000000008311171561032957600080fd5b9091929391929390505050610bcf565b60405180821515815260200191505060405180910390f35b6103bd6004803603606081101561036757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c88565b005b610401600480360360208110156103d557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ef3565b60405180821515815260200191505060405180910390f35b6104856004803603606081101561042f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f4c565b60405180821515815260200191505060405180910390f35b6104a561103a565b60405180821515815260200191505060405180910390f35b6104ff600480360360208110156104d357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611092565b005b6105436004803603602081101561051757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110aa565b005b6105fc6004803603606081101561055b57600080fd5b810190808035906020019064010000000081111561057857600080fd5b82018360208201111561058a57600080fd5b803590602001918460208302840111640100000000831117156105ac57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611370565b005b6106406004803603602081101561061457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611508565b005b6106a46004803603604081101561065857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115b5565b60405180821515815260200191505060405180910390f35b6106fe600480360360208110156106d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115c9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107326115db565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107df6004803603604081101561077457600080fd5b81019080803590602001909291908035906020019064010000000081111561079b57600080fd5b8201836020820111156107ad57600080fd5b803590602001918460018302840111640100000000831117156107cf57600080fd5b9091929391929390505050611601565b60405180821515815260200191505060405180910390f35b6108396004803603602081101561080d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061165a565b005b61089d6004803603604081101561085157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611670565b005b610940600480360360608110156108b557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156108fc57600080fd5b82018360208201111561090e57600080fd5b8035906020019184600183028401116401000000008311171561093057600080fd5b9091929391929390505050611905565b60405180821515815260200191505060405180910390f35b610a196004803603608081101561096e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109d557600080fd5b8201836020820111156109e757600080fd5b80359060200191846001830284011164010000000083111715610a0957600080fd5b9091929391929390505050611971565b005b610a7d60048036036040811015610a3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119de565b005b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610b20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143e46026913960400191505060405180910390fd5b610b2b816001611d0d565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610c7d86610c7885858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610c6a89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611e4e565b611fb790919063ffffffff16565b612087565b905095945050505050565b610c918361223e565b50610c9b83612685565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610d2f57610d29833283600067ffffffffffffffff81118015610cee57600080fd5b506040519080825280601f01601f191660200182016040528015610d215781602001600182028036833780820191505090505b506000612786565b50610e5d565b6060610dd38484600063a9059cbb60e01b3287604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506000612786565b9050600081511115610e5b57808060200190516020811015610df457600080fd5b8101908080519060200190929190505050610e5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061440a6035913960400191505060405180910390fd5b5b505b7feb5511fbef89123439f12682f0e9d0fc9696913b26eee55434c77d62c30aa7ca83328484604051808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060405180910390a1505050565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b60008060009050610f5d8585612087565b15610f6b576001905061102f565b61102c83600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff16151515158152602001600182015481525050612c5490919063ffffffff16565b90505b809150509392505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b61109b8161223e565b506110a7816001612ca3565b50565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661114b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143e46026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614156111ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f477561726465643a2063616e6e6f742072656d6f76652073656c66000000000081525060200191505060405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166112ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f477561726465643a20677561726469616e20646f65736e27742065786973740081525060200191505060405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fee943cdb81826d5909c559c6b1ae6908fcaf2dbc16c4b730346736b486283e8b3282604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180614318602f913960400191505060405180910390fd5b6000600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506114a2848480806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050612f05565b6114ac3083612f5d565b6114b581612f77565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505050565b6000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166115a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143e46026913960400191505060405180910390fd5b6115b281612fbb565b50565b60006115c18383612087565b905092915050565b60006115d4826131e2565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006116518484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613238565b90509392505050565b6116638161223e565b5061166d81612685565b50565b600061167b8361223e565b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806143b9602b913960400191505060405180910390fd5b6117b9600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff161515151581526020016001820154815250506132a5565b61180e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806142b7602c913960400191505060405180910390fd5b43600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f1ce3cbbc43ee231e5b950332f2b0b9dd7d349291a3ee411ce5c5c7ed745661bb8383604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050565b60006119678561196285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505087611fb790919063ffffffff16565b612087565b9050949350505050565b61197a8561223e565b5061198485612685565b6119d685858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506001612786565b505050505050565b6119e78261223e565b50600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180614498602d913960400191505060405180910390fd5b611b25600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900460ff161515151581526020016001820154815250506132a5565b15611b7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061446b602d913960400191505060405180910390fd5b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055506000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055507f27e282f7712c5b4617277759c834b86d163dfc1aad25c8c3c5926a1c9e5644688282604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b81526020018061421e603b913960400191505060405180910390fd5b81600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508015611e4a577f70d9f5a076620216a6050e493f3ce69749de0b68fa4b839ba2518660ba8b9cf0600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5050565b6000611e5a82516132b8565b826040516020018082805190602001908083835b60208310611e915780518252602082019150602081019050602083039250611e6e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405260405160200180807f19457468657265756d205369676e6564204d6573736167653a0a000000000000815250601a0183805190602001908083835b60208310611f235780518252602082019150602081019050602083039250611f00565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b60208310611f745780518252602082019150602081019050602083039250611f51565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052805190602001209050919050565b6000806000905060418351141561207d5760008060006020860151925060408601519150606086015160001a9050601b8160ff161015611ff857601b810190505b601b8160ff16148061200d5750601c8160ff16145b156120795760018782858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561206c573d6000803e3d6000fd5b5050506020604051035193505b5050505b8091505092915050565b600080600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16156121ac576000600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154149050612234565b6000801b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154141561223357612202836131e2565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505b5b8091505092915050565b6000806122496133ff565b9050600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16156123c0576000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154146123bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001806142596038913960400191505060405180910390fd5b61267c565b6000801b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101541461245d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001806142596038913960400191505060405180910390fd5b600081604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b81526014019150506040516020818303038152906040528051906020012090506124aa81613410565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461252d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001806142596038913960400191505060405180910390fd5b80600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055507f27e282f7712c5b4617277759c834b86d163dfc1aad25c8c3c5926a1c9e5644688483604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505b80915050919050565b600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1661278357612726600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546001613606565b506001600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055505b50565b6060600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16141561280e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806143476025913960400191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415612893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061443f602c913960400191505060405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415612918576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806142916026913960400191505060405180910390fd5b60608673ffffffffffffffffffffffffffffffffffffffff16633f579f428787876040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156129aa57808201518184015260208101905061298f565b50505050905090810190601f1680156129d75780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156129f857600080fd5b505af1158015612a0c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015612a3657600080fd5b8101908080516040519392919084640100000000821115612a5657600080fd5b83820191506020820185811115612a6c57600080fd5b8251866001820283011164010000000082111715612a8957600080fd5b8083526020830192505050908051906020019080838360005b83811015612abd578082015181840152602081019050612aa2565b50505050905090810190601f168015612aea5780820380516001836020036101000a031916815260200191505b5060405250505090508215612c47577f99eeae1fb8801e2e878e060ec5e5b3557b3c4f8106e35d88cb573f293dae4e248787878785604051808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612ba1578082015181840152602081019050612b86565b50505050905090810190601f168015612bce5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015612c07578082015181840152602081019050612bec565b50505050905090810190601f168015612c345780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a15b8091505095945050505050565b60008060009050836000015115612c9957600084602001511415612c7b5760019050612c98565b6000831415612c8d5760019050612c97565b8284602001511190505b5b5b8091505092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d2257600080fd5b505afa158015612d36573d6000803e3d6000fd5b505050506040513d6020811015612d4c57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff161415612dca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061438e602b913960400191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663d784d426600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b158015612e5557600080fd5b505af1158015612e69573d6000803e3d6000fd5b505050508015612f01577feec27cdb8bd6f55c2c537deb52ab094a2437e85ef5197e6f064f90bff3ff563f82600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b5050565b600081511415612f1d57612f1832612fbb565b612f5a565b60008151905060005b81811015612f5757612f4a838281518110612f3d57fe5b6020026020010151612fbb565b8080600101915050612f26565b50505b50565b612f6882600061375a565b612f73816000611d0d565b5050565b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561305e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f477561726465643a2063616e6e6f74206164642030783020677561726469616e81525060200191505060405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561311d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f477561726465643a20677561726469616e20616c72656164792065786973747381525060200191505060405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a3282604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b60008082604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b815260140191505060405160208183030381529060405280519060200120905061323081613410565b915050919050565b60008061324e8385611fb790919063ffffffff16565b90506000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1691505092915050565b60006132b18243612c54565b9050919050565b60606000821415613300576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506133fa565b600082905060005b6000821461332a578080600101915050600a828161332257fe5b049150613308565b60608167ffffffffffffffff8111801561334357600080fd5b506040519080825280601f01601f1916602001820160405280156133765781602001600182028036833780820191505090505b50905060006001830390508593505b600084146133f257600a848161339757fe5b0660300160f81b828280600190039350815181106133b157fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84816133ea57fe5b049350613385565b819450505050505b919050565b600061340b601461389b565b905090565b600060606040518060200161342490613a8c565b6020820181038252601f19601f82011660405250600060a01b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600060a01b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516020018086805190602001908083835b602083106134be578051825260208201915060208101905060208303925061349b565b6001836020036101000a0380198251168184511680821785525050505050509050018573ffffffffffffffffffffffffffffffffffffffff19168152600c018473ffffffffffffffffffffffffffffffffffffffff1660601b81526014018373ffffffffffffffffffffffffffffffffffffffff19168152600c018273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401955050505050506040516020818303038152906040529050600060ff60f81b3085848051906020012060405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018473ffffffffffffffffffffffffffffffffffffffff1660601b81526014018381526020018281526020019450505050506040516020818303038152906040528051906020012090508060001c92505050919050565b60008083600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405161365c90613a8c565b808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff168152602001925050508190604051809103906000f59050801580156136b9573d6000803e3d6000fd5b5090508215613750577f2682a218602b9036c9869f006c5405ee4a1a65267653eb7e286123e5e1afde4c81600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156137e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260358152602001806142e36035913960400191505060405180910390fd5b81600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508015613897577f02e3c47057b8dc27a0929d3c394c314c73aa002d46939c31c9f71d1e77e86c10600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5050565b600080600090506138aa613930565b1561392357600083600036905003905061391b600036839060148501926138d393929190613a99565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506139f3565b915050613927565b3390505b80915050919050565b600080600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156139ec57602c600036905010156139e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061436c6022913960400191505060405180910390fd5b600190505b8091505090565b6000806014835114613a6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f42797465734c69623a20696e76616c69642064617461206c656e67746800000081525060200191505060405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b61075180613acd83390190565b60008085851115613aa957600080fd5b83861115613ab657600080fd5b600185028301915084860390509450949250505056fe608060405234801561001057600080fd5b506040516107513803806107518339818101604052604081101561003357600080fd5b810190808051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610630806101216000396000f3fe60806040526004361061004e5760003560e01c80633f579f42146100be5780635c60da1b146101e75780637b10399914610228578063d784d42614610269578063f77c4791146102ba57610055565b3661005557005b34801561006157600080fd5b50600080369050146100bc576000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050368060008037600080826000855af43d806000803e81600081146100b757816000f35b816000fd5b005b3480156100ca57600080fd5b5061016c600480360360608110156100e157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561012857600080fd5b82018360208201111561013a57600080fd5b8035906020019184600183028401116401000000008311171561015c57600080fd5b90919293919293905050506102fb565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101ac578082015181840152602081019050610191565b50505050905090810190601f1680156101d95780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101f357600080fd5b506101fc61049f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561023457600080fd5b5061023d6104c5565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561027557600080fd5b506102b86004803603602081101561028c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104eb565b005b3480156102c657600080fd5b506102cf6105d3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806105f8602c913960400191505060405180910390fd5b606060008673ffffffffffffffffffffffffffffffffffffffff1686868660405180838380828437808301925050509250505060006040518083038185875af1925050503d8060008114610411576040519150601f19603f3d011682016040523d82523d6000602084013e610416565b606091505b50809350819250505080610492576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4163636f756e743a207472616e73616374696f6e20726576657274656400000081525060200191505060405180910390fd5b8192505050949350505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461058f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806105f8602c913960400191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fe436f6e74726f6c6c65643a206d73672e73656e646572206973206e6f742074686520636f6e74726f6c6c6572a164736f6c634300060c000a4163636f756e74436f6e74726f6c6c65723a2063616e6e6f7420736574206163636f756e7420496d706c656d656e746174696f6e20746f20307830506572736f6e616c4163636f756e7452656769737472793a2073656e646572206973206e6f7420746865206163636f756e74206f776e65724163636f756e74436f6e74726f6c6c65723a2063616e6e6f742073656e6420746f2073656c66506572736f6e616c4163636f756e7452656769737472793a206f776e657220646f65736e27742065786973744163636f756e74436f6e74726f6c6c65723a2063616e6e6f7420736574206163636f756e7420726567697374727920746f20307830496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a65724163636f756e74436f6e74726f6c6c65723a2063616e6e6f742073656e6420746f2030783047617465776179526563697069656e743a20696e76616c6964206d73672e646174614163636f756e74436f6e74726f6c6c65723a206163636f756e7420616c7265616479207570677261646564506572736f6e616c4163636f756e7452656769737472793a2063616e6e6f742072656d6f76652073656c66477561726465643a2074782e6f726967696e206973206e6f742074686520677561726469616e506572736f6e616c4163636f756e7452656769737472793a204552433230546f6b656e207472616e736665722072657665727465644163636f756e74436f6e74726f6c6c65723a2063616e6e6f742073656e6420746f20636f6e74726f6c6c6572506572736f6e616c4163636f756e7452656769737472793a206f776e657220616c726561647920657869737473506572736f6e616c4163636f756e7452656769737472793a2063616e6e6f742061646420307830206f776e6572a164736f6c634300060c000a", @@ -949,12 +949,12 @@ "type": "t_address" }, { - "astId": 6799, + "astId": 7519, "contract": "src/personal/PersonalAccountRegistry.sol:PersonalAccountRegistry", "label": "accounts", "offset": 0, "slot": "5", - "type": "t_mapping(t_address,t_struct(Account)6795_storage)" + "type": "t_mapping(t_address,t_struct(Account)7515_storage)" } ], "types": { @@ -980,12 +980,12 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_address,t_struct(Account)6795_storage)": { + "t_mapping(t_address,t_struct(Account)7515_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct PersonalAccountRegistry.Account)", "numberOfBytes": "32", - "value": "t_struct(Account)6795_storage" + "value": "t_struct(Account)7515_storage" }, "t_mapping(t_address,t_struct(BlockRelated)1382_storage)": { "encoding": "mapping", @@ -994,12 +994,12 @@ "numberOfBytes": "32", "value": "t_struct(BlockRelated)1382_storage" }, - "t_struct(Account)6795_storage": { + "t_struct(Account)7515_storage": { "encoding": "inplace", "label": "struct PersonalAccountRegistry.Account", "members": [ { - "astId": 6788, + "astId": 7508, "contract": "src/personal/PersonalAccountRegistry.sol:PersonalAccountRegistry", "label": "deployed", "offset": 0, @@ -1007,7 +1007,7 @@ "type": "t_bool" }, { - "astId": 6790, + "astId": 7510, "contract": "src/personal/PersonalAccountRegistry.sol:PersonalAccountRegistry", "label": "salt", "offset": 0, @@ -1015,7 +1015,7 @@ "type": "t_bytes32" }, { - "astId": 6794, + "astId": 7514, "contract": "src/personal/PersonalAccountRegistry.sol:PersonalAccountRegistry", "label": "owners", "offset": 0, diff --git a/deployments/neonDevnet/WrappedWeiToken.json b/deployments/neonDevnet/WrappedWeiToken.json index 7087889f..1bcda808 100644 --- a/deployments/neonDevnet/WrappedWeiToken.json +++ b/deployments/neonDevnet/WrappedWeiToken.json @@ -413,7 +413,7 @@ "type": "receive" } ], - "transactionHash": "0x914aca830634bfd34953e0964b78873ddce6d6c0a62161b7a5501b4b5ca196f5", + "transactionHash": "0x3da6fb813eb5a300a50d8fcd9e77655806bde218175c7187c05d0e36042b6348", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", @@ -421,16 +421,16 @@ "transactionIndex": 0, "gasUsed": "81195560", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa6eb5a102c551f2f14cde19e773b53c0e0422e6c79720d013e265428f734e169", - "transactionHash": "0x914aca830634bfd34953e0964b78873ddce6d6c0a62161b7a5501b4b5ca196f5", + "blockHash": "0x6c2cc52b0d1d2164122951c5ea1cd15b173d3e8e2d84275442ad480122e89635", + "transactionHash": "0x3da6fb813eb5a300a50d8fcd9e77655806bde218175c7187c05d0e36042b6348", "logs": [], - "blockNumber": 173997050, + "blockNumber": 178555358, "cumulativeGasUsed": "81195560", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "1bdf84d4bd28700579af1cc4796e2cae", + "solcInputHash": "c6bcc786074bb5f47af1ba8ec29021b3", "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"ConsumerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"ConsumerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"initializer\",\"type\":\"address\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"consumers_\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"gateway_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"isConsumer\",\"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\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startConsuming\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stopConsuming\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawAllTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Stanis\\u0142aw G\\u0142ogowski \",\"details\":\"After the transfer to consumer's account is done, the token will be automatically burned and withdrawn. Use `startConsuming` to become a consumer.\",\"events\":{\"ConsumerAdded(address)\":{\"details\":\"Emitted when the new consumer is added\",\"params\":{\"consumer\":\"consumer address\"}},\"ConsumerRemoved(address)\":{\"details\":\"Emitted when the existing consumer is removed\",\"params\":{\"consumer\":\"consumer address\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Public constructor\"},\"depositTo(address)\":{\"params\":{\"to\":\"to address\"}},\"initialize(address[],address)\":{\"params\":{\"consumers_\":\"array of consumers addresses\",\"gateway_\":\"`Gateway` contract address\"}},\"isConsumer(address)\":{\"params\":{\"consumer\":\"consumer address\"},\"returns\":{\"_0\":\"true if consumer exists\"}},\"isInitialized()\":{\"returns\":{\"_0\":\"true when contract is initialized\"}},\"startConsuming()\":{\"details\":\"Add caller as a consumer\"},\"stopConsuming()\":{\"details\":\"Remove caller from consumers\"},\"withdraw(uint256)\":{\"params\":{\"value\":\"value to withdraw\"}},\"withdrawAllTo(address)\":{\"params\":{\"to\":\"to address\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"to\":\"to address\",\"value\":\"value to withdraw\"}}},\"title\":\"Wrapped wei token\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"depositTo(address)\":{\"notice\":\"Deposits `msg.value` to address\"},\"initialize(address[],address)\":{\"notice\":\"Initializes `WrappedWeiToken` contract\"},\"isConsumer(address)\":{\"notice\":\"Checks if consumer exists\"},\"isInitialized()\":{\"notice\":\"Check if contract is initialized\"},\"startConsuming()\":{\"notice\":\"Starts consuming\"},\"stopConsuming()\":{\"notice\":\"Stops consuming\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws\"},\"withdrawAll()\":{\"notice\":\"Withdraws all\"},\"withdrawAllTo(address)\":{\"notice\":\"Withdraws all to address\"},\"withdrawTo(address,uint256)\":{\"notice\":\"Withdraws to address\"}},\"notice\":\"One to one wei consumable ERC20 token\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/tokens/WrappedWeiToken.sol\":\"WrappedWeiToken\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"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/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/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/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/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/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\\u0142aw G\\u0142ogowski \\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\",\"keccak256\":\"0xa4e1ef99b7ce5b92cedb73387e5954824815e13ac23acef38d7fcf234d8fc017\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x60806040523480156200001157600080fd5b50326000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518060400160405280600b81526020017f5772617070656420576569000000000000000000000000000000000000000000815250600190805190602001906200009f929190620000f4565b506040518060400160405280600481526020017f575745490000000000000000000000000000000000000000000000000000000081525060029080519060200190620000ed929190620000f4565b506200019a565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200013757805160ff191683800117855562000168565b8280016001018555821562000168579182015b82811115620001675782518255916020019190600101906200014a565b5b5090506200017791906200017b565b5090565b5b80821115620001965760008160009055506001016200017c565b5090565b6120b080620001aa6000396000f3fe6080604052600436106101235760003560e01c806356a3b64b116100a0578063a9059cbb11610064578063a9059cbb1461065f578063b760faf9146106d0578063ca9add8f14610714578063dd62ed3e14610765578063f55647e0146107ea5761013b565b806356a3b64b146104d557806370a08231146104ec578063834ff73914610551578063853828b6146105b857806395d89b41146105cf5761013b565b806323b872dd116100e757806323b872dd146103085780632e1a7d4d14610399578063313ce567146103d4578063392e53cd14610402578063462d0b2e1461042f5761013b565b806306fdde0314610140578063095ea7b3146101d0578063116191b61461024157806318160ddd14610282578063205c2878146102ad5761013b565b3661013b57610139610133610801565b34610810565b005b600080fd5b34801561014c57600080fd5b50610155610a26565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561019557808201518184015260208101905061017a565b50505050905090810190601f1680156101c25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101dc57600080fd5b50610229600480360360408110156101f357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610ac4565b60405180821515815260200191505060405180910390f35b34801561024d57600080fd5b50610256610ae2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561028e57600080fd5b50610297610b08565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b50610306600480360360408110156102d057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b0e565b005b34801561031457600080fd5b506103816004803603606081101561032b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b24565b60405180821515815260200191505060405180910390f35b3480156103a557600080fd5b506103d2600480360360208110156103bc57600080fd5b8101908080359060200190929190505050610be1565b005b3480156103e057600080fd5b506103e9610bfd565b604051808260ff16815260200191505060405180910390f35b34801561040e57600080fd5b50610417610c10565b60405180821515815260200191505060405180910390f35b34801561043b57600080fd5b506104d36004803603604081101561045257600080fd5b810190808035906020019064010000000081111561046f57600080fd5b82018360208201111561048157600080fd5b803590602001918460208302840111640100000000831117156104a357600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c66565b005b3480156104e157600080fd5b506104ea610e05565b005b3480156104f857600080fd5b5061053b6004803603602081101561050f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e17565b6040518082815260200191505060405180910390f35b34801561055d57600080fd5b506105a06004803603602081101561057457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e60565b60405180821515815260200191505060405180910390f35b3480156105c457600080fd5b506105cd610eb6565b005b3480156105db57600080fd5b506105e4610f0f565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610624578082015181840152602081019050610609565b50505050905090810190601f1680156106515780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561066b57600080fd5b506106b86004803603604081101561068257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610fad565b60405180821515815260200191505060405180910390f35b610712600480360360208110156106e657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fcb565b005b34801561072057600080fd5b506107636004803603602081101561073757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fd8565b005b34801561077157600080fd5b506107d46004803603604081101561078857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611032565b6040518082815260200191505060405180910390f35b3480156107f657600080fd5b506107ff6110b9565b005b600061080b61120f565b905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610896576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180611fb66026913960400191505060405180910390fd5b6000811161090c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4552433230546f6b656e3a2063616e6e6f74206d696e7420302076616c75650081525060200191505060405180910390fd5b61095e81600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461122090919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109b68160045461122090919063ffffffff16565b6004819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610abc5780601f10610a9157610100808354040283529160200191610abc565b820191906000526020600020905b815481529060010190602001808311610a9f57829003601f168201915b505050505081565b6000610ad8610ad1610801565b84846112a8565b6001905092915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b610b20610b19610801565b838361149f565b5050565b600080610b2f610801565b9050610b3c858585611538565b610bd58582610bd086600660008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546115ab90919063ffffffff16565b6112a8565b60019150509392505050565b610bfa610bec610801565b610bf4610801565b8361149f565b50565b600360009054906101000a900460ff1681565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610d0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180611ec8602f913960400191505060405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008383905014610daa57600083839050905060005b81811015610da757610d9a858583818110610d7857fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166115d8565b8080600101915050610d61565b50505b610db381611723565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b610e15610e10610801565b6115d8565b565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000610ec0610801565b9050610f0c8182600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461149f565b50565b60028054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fa55780601f10610f7a57610100808354040283529160200191610fa5565b820191906000526020600020905b815481529060010190602001808311610f8857829003601f168201915b505050505081565b6000610fc1610fba610801565b8484611538565b6001905092915050565b610fd58134610810565b50565b6000610fe2610801565b905061102e8183600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461149f565b5050565b6000600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60006110c3610801565b9050600860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611167576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806120066027913960400191505060405180910390fd5b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fe3f5ed5f263f1f01764a96edfc7d025f511ec5f7d180e8816908b78bcf74f09881604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600061121b6028611767565b905090565b60008082840190508381101561129e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174684c69623a206164646974696f6e206f766572666c6f77000081525060200191505060405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561132e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180611f8b602b913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156113b4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180611f416029913960400191505060405180910390fd5b80600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b6114a983826117fc565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050611533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061202d6025913960400191505060405180910390fd5b505050565b600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561159a5761159583838361149f565b6115a6565b6115a58383836119b6565b5b505050565b60006115d08383604051806060016040528060218152602001611f6a60219139611c56565b905092915050565b600860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561167b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180611ef76028913960400191505060405180910390fd5b6001600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f28b26e7a3d20aedbc5f8f2ebf7da671c0491723a2b78f47a097b0e46dee0714281604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060009050611776611d10565b156117ef5760008360003690500390506117e76000368390601485019261179f93929190611e6c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611dd3565b9150506117f3565b3390505b80915050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611882576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180611ea06028913960400191505060405180910390fd5b6118ee8160405180606001604052806026815260200161205260269139600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611c569092919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611946816004546115ab90919063ffffffff16565b600481905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611a3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180612078602c913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ac2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611fdc602a913960400191505060405180910390fd5b611b1481600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546115ab90919063ffffffff16565b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611ba981600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461122090919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290611d03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611cc8578082015181840152602081019050611cad565b50505050905090810190601f168015611cf55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5082840390509392505050565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415611dcc57602c60003690501015611dc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611f1f6022913960400191505060405180910390fd5b600190505b8091505090565b6000806014835114611e4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f42797465734c69623a20696e76616c69642064617461206c656e67746800000081525060200191505060405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b60008085851115611e7c57600080fd5b83861115611e8957600080fd5b600185028301915084860390509450949250505056fe4552433230546f6b656e3a2063616e6e6f74206275726e2066726f6d203078302061646472657373496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a657257726170706564576569546f6b656e3a20636f6e73756d657220616c72656164792065786973747347617465776179526563697069656e743a20696e76616c6964206d73672e646174614552433230546f6b656e3a2063616e6e6f7420617070726f766520746f203078302061646472657373536166654d6174684c69623a207375627472616374696f6e206f766572666c6f774552433230546f6b656e3a2063616e6e6f7420617070726f76652066726f6d2030783020616464726573734552433230546f6b656e3a2063616e6e6f74206d696e7420746f2030783020616464726573734552433230546f6b656e3a2063616e6e6f74207472616e7366657220746f20307830206164647265737357726170706564576569546f6b656e3a20636f6e73756d657220646f65736e277420657869737457726170706564576569546f6b656e3a207472616e73616374696f6e2072657665727465644552433230546f6b656e3a206275726e2076616c756520657863656564732062616c616e63654552433230546f6b656e3a2063616e6e6f74207472616e736665722066726f6d203078302061646472657373a164736f6c634300060c000a", "deployedBytecode": "0x6080604052600436106101235760003560e01c806356a3b64b116100a0578063a9059cbb11610064578063a9059cbb1461065f578063b760faf9146106d0578063ca9add8f14610714578063dd62ed3e14610765578063f55647e0146107ea5761013b565b806356a3b64b146104d557806370a08231146104ec578063834ff73914610551578063853828b6146105b857806395d89b41146105cf5761013b565b806323b872dd116100e757806323b872dd146103085780632e1a7d4d14610399578063313ce567146103d4578063392e53cd14610402578063462d0b2e1461042f5761013b565b806306fdde0314610140578063095ea7b3146101d0578063116191b61461024157806318160ddd14610282578063205c2878146102ad5761013b565b3661013b57610139610133610801565b34610810565b005b600080fd5b34801561014c57600080fd5b50610155610a26565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561019557808201518184015260208101905061017a565b50505050905090810190601f1680156101c25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101dc57600080fd5b50610229600480360360408110156101f357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610ac4565b60405180821515815260200191505060405180910390f35b34801561024d57600080fd5b50610256610ae2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561028e57600080fd5b50610297610b08565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b50610306600480360360408110156102d057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b0e565b005b34801561031457600080fd5b506103816004803603606081101561032b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b24565b60405180821515815260200191505060405180910390f35b3480156103a557600080fd5b506103d2600480360360208110156103bc57600080fd5b8101908080359060200190929190505050610be1565b005b3480156103e057600080fd5b506103e9610bfd565b604051808260ff16815260200191505060405180910390f35b34801561040e57600080fd5b50610417610c10565b60405180821515815260200191505060405180910390f35b34801561043b57600080fd5b506104d36004803603604081101561045257600080fd5b810190808035906020019064010000000081111561046f57600080fd5b82018360208201111561048157600080fd5b803590602001918460208302840111640100000000831117156104a357600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c66565b005b3480156104e157600080fd5b506104ea610e05565b005b3480156104f857600080fd5b5061053b6004803603602081101561050f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e17565b6040518082815260200191505060405180910390f35b34801561055d57600080fd5b506105a06004803603602081101561057457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e60565b60405180821515815260200191505060405180910390f35b3480156105c457600080fd5b506105cd610eb6565b005b3480156105db57600080fd5b506105e4610f0f565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610624578082015181840152602081019050610609565b50505050905090810190601f1680156106515780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561066b57600080fd5b506106b86004803603604081101561068257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610fad565b60405180821515815260200191505060405180910390f35b610712600480360360208110156106e657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fcb565b005b34801561072057600080fd5b506107636004803603602081101561073757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fd8565b005b34801561077157600080fd5b506107d46004803603604081101561078857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611032565b6040518082815260200191505060405180910390f35b3480156107f657600080fd5b506107ff6110b9565b005b600061080b61120f565b905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610896576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180611fb66026913960400191505060405180910390fd5b6000811161090c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4552433230546f6b656e3a2063616e6e6f74206d696e7420302076616c75650081525060200191505060405180910390fd5b61095e81600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461122090919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109b68160045461122090919063ffffffff16565b6004819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610abc5780601f10610a9157610100808354040283529160200191610abc565b820191906000526020600020905b815481529060010190602001808311610a9f57829003601f168201915b505050505081565b6000610ad8610ad1610801565b84846112a8565b6001905092915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b610b20610b19610801565b838361149f565b5050565b600080610b2f610801565b9050610b3c858585611538565b610bd58582610bd086600660008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546115ab90919063ffffffff16565b6112a8565b60019150509392505050565b610bfa610bec610801565b610bf4610801565b8361149f565b50565b600360009054906101000a900460ff1681565b60008073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610d0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180611ec8602f913960400191505060405180910390fd5b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008383905014610daa57600083839050905060005b81811015610da757610d9a858583818110610d7857fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166115d8565b8080600101915050610d61565b50505b610db381611723565b7f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e632604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b610e15610e10610801565b6115d8565b565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000610ec0610801565b9050610f0c8182600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461149f565b50565b60028054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fa55780601f10610f7a57610100808354040283529160200191610fa5565b820191906000526020600020905b815481529060010190602001808311610f8857829003601f168201915b505050505081565b6000610fc1610fba610801565b8484611538565b6001905092915050565b610fd58134610810565b50565b6000610fe2610801565b905061102e8183600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461149f565b5050565b6000600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60006110c3610801565b9050600860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611167576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806120066027913960400191505060405180910390fd5b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fe3f5ed5f263f1f01764a96edfc7d025f511ec5f7d180e8816908b78bcf74f09881604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600061121b6028611767565b905090565b60008082840190508381101561129e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174684c69623a206164646974696f6e206f766572666c6f77000081525060200191505060405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561132e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180611f8b602b913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156113b4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180611f416029913960400191505060405180910390fd5b80600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b6114a983826117fc565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050611533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061202d6025913960400191505060405180910390fd5b505050565b600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561159a5761159583838361149f565b6115a6565b6115a58383836119b6565b5b505050565b60006115d08383604051806060016040528060218152602001611f6a60219139611c56565b905092915050565b600860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561167b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180611ef76028913960400191505060405180910390fd5b6001600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f28b26e7a3d20aedbc5f8f2ebf7da671c0491723a2b78f47a097b0e46dee0714281604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060009050611776611d10565b156117ef5760008360003690500390506117e76000368390601485019261179f93929190611e6c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611dd3565b9150506117f3565b3390505b80915050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611882576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180611ea06028913960400191505060405180910390fd5b6118ee8160405180606001604052806026815260200161205260269139600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611c569092919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611946816004546115ab90919063ffffffff16565b600481905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611a3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180612078602c913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ac2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611fdc602a913960400191505060405180910390fd5b611b1481600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546115ab90919063ffffffff16565b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611ba981600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461122090919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290611d03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611cc8578082015181840152602081019050611cad565b50505050905090810190601f168015611cf55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5082840390509392505050565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415611dcc57602c60003690501015611dc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611f1f6022913960400191505060405180910390fd5b600190505b8091505090565b6000806014835114611e4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f42797465734c69623a20696e76616c69642064617461206c656e67746800000081525060200191505060405180910390fd5b6c01000000000000000000000000602084015104905080915050919050565b60008085851115611e7c57600080fd5b83861115611e8957600080fd5b600185028301915084860390509450949250505056fe4552433230546f6b656e3a2063616e6e6f74206275726e2066726f6d203078302061646472657373496e697469616c697a61626c653a2074782e6f726967696e206973206e6f742074686520696e697469616c697a657257726170706564576569546f6b656e3a20636f6e73756d657220616c72656164792065786973747347617465776179526563697069656e743a20696e76616c6964206d73672e646174614552433230546f6b656e3a2063616e6e6f7420617070726f766520746f203078302061646472657373536166654d6174684c69623a207375627472616374696f6e206f766572666c6f774552433230546f6b656e3a2063616e6e6f7420617070726f76652066726f6d2030783020616464726573734552433230546f6b656e3a2063616e6e6f74206d696e7420746f2030783020616464726573734552433230546f6b656e3a2063616e6e6f74207472616e7366657220746f20307830206164647265737357726170706564576569546f6b656e3a20636f6e73756d657220646f65736e277420657869737457726170706564576569546f6b656e3a207472616e73616374696f6e2072657665727465644552433230546f6b656e3a206275726e2076616c756520657863656564732062616c616e63654552433230546f6b656e3a2063616e6e6f74207472616e736665722066726f6d203078302061646472657373a164736f6c634300060c000a", @@ -610,7 +610,7 @@ "type": "t_address" }, { - "astId": 7468, + "astId": 8188, "contract": "src/tokens/WrappedWeiToken.sol:WrappedWeiToken", "label": "consumers", "offset": 0, diff --git a/deployments/neonDevnet/solcInputs/6ff48c01406545b171c1098ac74d4555.json b/deployments/neonDevnet/solcInputs/6ff48c01406545b171c1098ac74d4555.json new file mode 100644 index 00000000..d75f181a --- /dev/null +++ b/deployments/neonDevnet/solcInputs/6ff48c01406545b171c1098ac74d4555.json @@ -0,0 +1,97 @@ +{ + "language": "Solidity", + "sources": { + "src/bridges/facets/StargateFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.4;\n\nimport {IStargateRouter} from \"../interfaces/IStargateRouter.sol\";\nimport {IStargateReceiver} from \"../interfaces/IStargateReceiver.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {ReentrancyGuard} from \"../../common/helpers/DiamondReentrancyGuard.sol\";\nimport {CannotBridgeToSameNetwork, InvalidAmount, InvalidConfig} from \"../errors/GenericErrors.sol\";\nimport {SenderNotStargateRouter, NoMsgValueForCrossChainMessage, StargateRouterAddressZero, InvalidSourcePoolId, InvalidDestinationPoolId} from \"../errors/StargateErrors.sol\";\nimport {LibDiamond} from \"../libs/LibDiamond.sol\";\n\n/// @title StargateFacet\n/// @author Luke Wickens \n/// @notice Stargate/LayerZero intergration for bridging tokens\n\ncontract StargateFacet is IStargateReceiver, ReentrancyGuard {\n using SafeERC20 for IERC20;\n\n //////////////////////////////////////////////////////////////\n /////////////////////////// Events ///////////////////////////\n //////////////////////////////////////////////////////////////\n event SGInitialized(address stargate, uint16 chainId);\n event SGTransferStarted(\n string bridgeUsed,\n address fromToken,\n address toToken,\n address from,\n address to,\n uint256 amount,\n uint16 chainIdTo\n );\n event SGReceivedOnDestination(address token, uint256 amount);\n event SGUpdatedRouter(address newAddress);\n event SGUpdatedSlippageTolerance(uint256 newSlippage);\n event SGAddedPool(uint16 chainId, address token, uint16 poolId);\n\n //////////////////////////////////////////////////////////////\n ////////////////////////// Storage ///////////////////////////\n //////////////////////////////////////////////////////////////\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"io.etherspot.facets.stargate\");\n struct Storage {\n address stargateRouter;\n uint16 chainId;\n uint256 dstGas;\n uint256 slippage;\n mapping(uint16 => mapping(address => uint16)) poolIds;\n }\n\n //////////////////////////////////////////////////////////////\n ////////////////////////// Structs ///////////////////////////\n //////////////////////////////////////////////////////////////\n\n struct StargateData {\n uint256 qty;\n address fromToken;\n address toToken;\n uint16 dstChainId;\n address to;\n address destStargateComposed;\n }\n\n /// @notice initializes state variables for the Stargate facet\n /// @param _stargateRouter - address of the Stargate router contract\n /// @param _chainId - current chain id\n function sgInitialize(address _stargateRouter, uint16 _chainId) external {\n if (_stargateRouter == address(0)) revert InvalidConfig();\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n s.stargateRouter = address(_stargateRouter);\n s.chainId = _chainId;\n s.slippage = 50; // equates to 0.5%\n // Adding pre-existing pools => USDC: 1, USDT: 2, BUSD: 5\n sgAddPool(1, 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, 1);\n sgAddPool(1, 0xdAC17F958D2ee523a2206206994597C13D831ec7, 2);\n sgAddPool(2, 0x55d398326f99059fF775485246999027B3197955, 2);\n sgAddPool(2, 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56, 5);\n sgAddPool(6, 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E, 1);\n sgAddPool(6, 0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7, 2);\n sgAddPool(9, 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174, 1);\n sgAddPool(9, 0xc2132D05D31c914a87C6611C10748AEb04B58e8F, 2);\n sgAddPool(10, 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8, 1);\n sgAddPool(10, 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9, 2);\n sgAddPool(11, 0x7F5c764cBc14f9669B88837ca1490cCa17c31607, 1);\n sgAddPool(12, 0x04068DA6C83AFCFA0e13ba15A6696662335D5B75, 1);\n emit SGInitialized(_stargateRouter, _chainId);\n }\n\n /// @notice initializes state variables for the stargate facet\n /// @param _sgData - struct containing information required to execute bridge\n function sgBridgeTokens(StargateData memory _sgData)\n external\n payable\n nonReentrant\n {\n // if (msg.value <= 0) revert NoMsgValueForCrossChainMessage();\n if (_sgData.qty <= 0) revert InvalidAmount();\n if (\n _sgData.fromToken == address(0) ||\n _sgData.toToken == address(0) ||\n _sgData.to == address(0) ||\n _sgData.destStargateComposed == address(0)\n ) revert InvalidConfig();\n\n // access storage\n Storage storage s = getStorage();\n\n // check pool ids are valid\n uint16 srcPoolId = sgRetrievePoolId(s.chainId, _sgData.fromToken);\n if (srcPoolId == 0) revert InvalidSourcePoolId();\n uint16 dstPoolId = sgRetrievePoolId(\n _sgData.dstChainId,\n _sgData.toToken\n );\n\n // calculate cross chain fees\n uint256 fees = sgCalculateFees(\n _sgData.dstChainId,\n _sgData.to,\n s.stargateRouter\n );\n\n // calculate slippage\n uint256 minAmountOut = sgMinAmountOut(_sgData.qty);\n\n // encode sgReceive implemented\n bytes memory destination = abi.encodePacked(\n _sgData.destStargateComposed\n );\n\n // encode payload data to send to destination contract, which it will handle with sgReceive()\n bytes memory payload = abi.encode(_sgData.to);\n\n // this contract calls stargate swap()\n IERC20(_sgData.fromToken).safeTransferFrom(\n msg.sender,\n address(this),\n _sgData.qty\n );\n\n IERC20(_sgData.fromToken).safeApprove(\n address(s.stargateRouter),\n _sgData.qty\n );\n\n // Stargate's Router.swap() function sends the tokens to the destination chain.\n IStargateRouter(s.stargateRouter).swap{value: fees}(\n _sgData.dstChainId, // the destination chain id\n srcPoolId, // the source Stargate poolId\n dstPoolId, // the destination Stargate poolId\n payable(msg.sender), // refund adddress. if msg.sender pays too much gas, return extra eth\n _sgData.qty, // total tokens to send to destination chain\n minAmountOut, // min amount allowed out\n IStargateRouter.lzTxObj(200000, 0, \"0x\"), // default lzTxObj\n destination, // destination address, the sgReceive() implementer\n payload // bytes payload\n );\n\n emit SGTransferStarted(\n \"stargate\",\n _sgData.fromToken,\n _sgData.toToken,\n msg.sender,\n _sgData.to,\n _sgData.qty,\n _sgData.dstChainId\n );\n }\n\n /// @notice required to receive tokens on destination chain\n /// @param _chainId The remote chainId sending the tokens\n /// @param _srcAddress The remote Bridge address\n /// @param _nonce The message ordering nonce\n /// @param _token The token contract on the local chain\n /// @param amountLD The qty of local _token contract tokens\n /// @param _payload The bytes containing the toAddress\n function sgReceive(\n uint16 _chainId,\n bytes memory _srcAddress,\n uint256 _nonce,\n address _token,\n uint256 amountLD,\n bytes memory _payload\n ) external override {\n Storage storage s = getStorage();\n if (msg.sender != address(s.stargateRouter))\n revert SenderNotStargateRouter();\n\n address _toAddr = abi.decode(_payload, (address));\n IERC20(_token).transfer(_toAddr, amountLD);\n emit SGReceivedOnDestination(_token, amountLD);\n }\n\n /// @notice Calculates cross chain fee\n /// @param _destChain Destination chain id\n /// @param _receiver Receiver on destination chain\n /// @param _router Address of stargate router\n function sgCalculateFees(\n uint16 _destChain,\n address _receiver,\n address _router\n ) public view returns (uint256) {\n (uint256 nativeFee, ) = IStargateRouter(_router).quoteLayerZeroFee(\n _destChain, // destination chain id\n 1, // 1 = swap\n abi.encodePacked(_receiver), // receiver on destination chain\n \"0x\", // payload, using abi.encode()\n IStargateRouter.lzTxObj(200000, 0, \"0x\")\n );\n return nativeFee;\n }\n\n /// @notice Calculates the minimum amount out using slippage tolerance\n /// @param _amount Transfer amount\n function sgMinAmountOut(uint256 _amount) public view returns (uint256) {\n Storage storage s = getStorage();\n // equates to 0.5% slippage\n return (_amount * (10000 - s.slippage)) / (10000);\n }\n\n /// @notice Updates stargate router address for deployed chain\n /// @param _newAddress Address of the new router\n function sgUpdateRouter(address _newAddress) external {\n LibDiamond.enforceIsContractOwner();\n if (_newAddress == address(0)) revert StargateRouterAddressZero();\n Storage storage s = getStorage();\n s.stargateRouter = address(_newAddress);\n emit SGUpdatedRouter(_newAddress);\n }\n\n /// @notice Updates slippage tolerance amount\n /// @param _newSlippage New slippage amount\n function sgUpdateSlippageTolerance(uint256 _newSlippage) external {\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n s.slippage = _newSlippage;\n emit SGUpdatedSlippageTolerance(_newSlippage);\n }\n\n /// @notice Adds a new pool for a specific token and chain\n /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\n /// @param _token Address of token\n /// @param _poolId Pool id (check stargate pool ids docs)\n function sgAddPool(\n uint16 _chainId,\n address _token,\n uint16 _poolId\n ) public {\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n s.poolIds[_chainId][_token] = _poolId;\n emit SGAddedPool(_chainId, _token, _poolId);\n }\n\n /// @notice Checks for a valid token pool on specific chain\n /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\n /// @param _token Address of token\n /// @param _poolId Pool id (check stargate pool ids docs)\n function sgCheckPoolId(\n uint16 _chainId,\n address _token,\n uint16 _poolId\n ) external view returns (bool) {\n Storage storage s = getStorage();\n return s.poolIds[_chainId][_token] == _poolId ? true : false;\n }\n\n /// @notice Retrieves pool id for a token on a specified chain\n /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\n /// @param _token Address of token\n function sgRetrievePoolId(uint16 _chainId, address _token)\n public\n view\n returns (uint16)\n {\n Storage storage s = getStorage();\n return s.poolIds[_chainId][_token];\n }\n\n //////////////////////////////////////////////////////////////\n ////////////////////// Private Functions /////////////////////\n //////////////////////////////////////////////////////////////\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/bridges/interfaces/IStargateRouter.sol": { + "content": "// SPDX-License-Identifier:MIT\n\npragma solidity 0.8.4;\npragma abicoder v2;\n\ninterface IStargateRouter {\n struct lzTxObj {\n uint256 dstGasForCall;\n uint256 dstNativeAmount;\n bytes dstNativeAddr;\n }\n\n function addLiquidity(\n uint256 _poolId,\n uint256 _amountLD,\n address _to\n ) external;\n\n function swap(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress,\n uint256 _amountLD,\n uint256 _minAmountLD,\n lzTxObj memory _lzTxParams,\n bytes calldata _to,\n bytes calldata _payload\n ) external payable;\n\n function redeemRemote(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress,\n uint256 _amountLP,\n uint256 _minAmountLD,\n bytes calldata _to,\n lzTxObj memory _lzTxParams\n ) external payable;\n\n function instantRedeemLocal(\n uint16 _srcPoolId,\n uint256 _amountLP,\n address _to\n ) external returns (uint256);\n\n function redeemLocal(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress,\n uint256 _amountLP,\n bytes calldata _to,\n lzTxObj memory _lzTxParams\n ) external payable;\n\n function sendCredits(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress\n ) external payable;\n\n function quoteLayerZeroFee(\n uint16 _dstChainId,\n uint8 _functionType,\n bytes calldata _toAddress,\n bytes calldata _transferAndCallPayload,\n lzTxObj memory _lzTxParams\n ) external view returns (uint256, uint256);\n}\n" + }, + "src/bridges/interfaces/IStargateReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.4;\n\ninterface IStargateReceiver {\n function sgReceive(\n uint16 _srcChainId, // the remote chainId sending the tokens\n bytes memory _srcAddress, // the remote Bridge address\n uint256 _nonce,\n address _token, // the token contract on the local chain\n uint256 amountLD, // the qty of local _token contract tokens\n bytes memory payload\n ) external;\n}\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\npragma solidity 0.8.4;\n\n/// @title Reentrancy Guard\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n //////////////////////////////////////////////////////////////\n ////////////////////////// Storage ///////////////////////////\n //////////////////////////////////////////////////////////////\n\n bytes32 private constant NAMESPACE =\n keccak256(\"io.etherspot.helpers.reentrancyguard\");\n\n //////////////////////////////////////////////////////////////\n ////////////////////////// Structs ///////////////////////////\n //////////////////////////////////////////////////////////////\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n //////////////////////////////////////////////////////////////\n ////////////////////////// Errors ////////////////////////////\n //////////////////////////////////////////////////////////////\n\n error ReentrancyError();\n\n //////////////////////////////////////////////////////////////\n ///////////////////////// Constants //////////////////////////\n //////////////////////////////////////////////////////////////\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n //////////////////////////////////////////////////////////////\n ///////////////////////// Modifiers ///////////////////////////\n //////////////////////////////////////////////////////////////\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n //////////////////////////////////////////////////////////////\n ////////////////////// Private Functions /////////////////////\n //////////////////////////////////////////////////////////////\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/bridges/errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable-next-line\npragma solidity 0.8.4;\n\nerror InvalidAmount();\nerror TokenAddressIsZero();\nerror CannotBridgeToSameNetwork();\nerror ZeroPostSwapBalance();\nerror InvalidBridgeConfigLength();\nerror NoSwapDataProvided();\nerror NativeValueWithERC();\nerror ContractCallNotAllowed();\nerror NullAddrIsNotAValidSpender();\nerror NullAddrIsNotAnERC20Token();\nerror NoTransferToNullAddress();\nerror NativeAssetTransferFailed();\nerror InvalidContract();\nerror InvalidConfig();\nerror ZeroAddressProvided();\n" + }, + "src/bridges/errors/StargateErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable-next-line\npragma solidity 0.8.4;\n\nerror SenderNotStargateRouter();\nerror NoMsgValueForCrossChainMessage();\nerror StargateRouterAddressZero();\nerror InvalidSourcePoolId();\nerror InvalidDestinationPoolId();\n" + }, + "src/bridges/libs/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4 <0.9.0;\n\nimport {IDiamondCut} from \"../interfaces/IDiamondCut.sol\";\n\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n require(\n msg.sender == diamondStorage().contractOwner,\n \"LibDiamond: Must be contract owner\"\n );\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (\n uint256 facetIndex;\n facetIndex < _diamondCut.length;\n facetIndex++\n ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n require(\n _functionSelectors.length > 0,\n \"LibDiamondCut: No selectors in facet to cut\"\n );\n DiamondStorage storage ds = diamondStorage();\n require(\n _facetAddress != address(0),\n \"LibDiamondCut: Add facet can't be address(0)\"\n );\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n selectorIndex++\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n require(\n oldFacetAddress == address(0),\n \"LibDiamondCut: Can't add function that already exists\"\n );\n addFunction(ds, selector, selectorPosition, _facetAddress);\n selectorPosition++;\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n require(\n _functionSelectors.length > 0,\n \"LibDiamondCut: No selectors in facet to cut\"\n );\n DiamondStorage storage ds = diamondStorage();\n require(\n _facetAddress != address(0),\n \"LibDiamondCut: Add facet can't be address(0)\"\n );\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n selectorIndex++\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n require(\n oldFacetAddress != _facetAddress,\n \"LibDiamondCut: Can't replace function with same function\"\n );\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n selectorPosition++;\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n require(\n _functionSelectors.length > 0,\n \"LibDiamondCut: No selectors in facet to cut\"\n );\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n require(\n _facetAddress == address(0),\n \"LibDiamondCut: Remove facet address must be address(0)\"\n );\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n selectorIndex++\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n }\n }\n\n function addFacet(DiamondStorage storage ds, address _facetAddress)\n internal\n {\n enforceHasContractCode(\n _facetAddress,\n \"LibDiamondCut: New facet has no code\"\n );\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n require(\n _facetAddress != address(0),\n \"LibDiamondCut: Can't remove function that doesn't exist\"\n );\n // an immutable function is a function defined directly in a diamond\n require(\n _facetAddress != address(this),\n \"LibDiamondCut: Can't remove immutable function\"\n );\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(address _init, bytes memory _calldata)\n internal\n {\n if (_init == address(0)) {\n require(\n _calldata.length == 0,\n \"LibDiamondCut: _init is address(0) but_calldata is not empty\"\n );\n } else {\n require(\n _calldata.length > 0,\n \"LibDiamondCut: _calldata is empty but _init is not address(0)\"\n );\n if (_init != address(this)) {\n enforceHasContractCode(\n _init,\n \"LibDiamondCut: _init address has no code\"\n );\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert(\"LibDiamondCut: _init function reverted\");\n }\n }\n }\n }\n\n function enforceHasContractCode(\n address _contract,\n string memory _errorMessage\n ) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize > 0, _errorMessage);\n }\n}\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\npragma solidity >=0.8.4 <0.9.0;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/bridges/libs/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n// solhint-disable-next-line\npragma solidity 0.8.4;\nimport {NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeValueWithERC, NativeAssetTransferFailed} from \"../errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @title LibAsset\n/// @author Connext \n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_INT = type(uint256).max;\n\n address internal constant NULL_ADDRESS =\n 0x0000000000000000000000000000000000000000; //address(0)\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n assetId == NATIVE_ASSETID\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(address payable recipient, uint256 amount)\n private\n {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice Gives MAX approval for another address to spend tokens\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (address(assetId) == NATIVE_ASSETID) return;\n if (spender == NULL_ADDRESS) revert NullAddrIsNotAValidSpender();\n uint256 allowance = assetId.allowance(address(this), spender);\n if (allowance < amount)\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_INT);\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) revert NullAddrIsNotAnERC20Token();\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (assetId == NATIVE_ASSETID) revert NullAddrIsNotAnERC20Token();\n if (to == NULL_ADDRESS) revert NoTransferToNullAddress();\n SafeERC20.safeTransferFrom(IERC20(assetId), from, to, amount);\n }\n\n /// @notice Deposits an asset into the contract and performs checks to avoid NativeValueWithERC\n /// @param tokenId Token to deposit\n /// @param amount Amount to deposit\n /// @param isNative Wether the token is native or ERC20\n function depositAsset(\n address tokenId,\n uint256 amount,\n bool isNative\n ) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNative) {\n if (msg.value != amount) revert InvalidAmount();\n } else {\n if (msg.value != 0) revert NativeValueWithERC();\n uint256 _fromTokenBalance = LibAsset.getOwnBalance(tokenId);\n LibAsset.transferFromERC20(\n tokenId,\n msg.sender,\n address(this),\n amount\n );\n if (LibAsset.getOwnBalance(tokenId) - _fromTokenBalance != amount)\n revert InvalidAmount();\n }\n }\n\n /// @notice Overload for depositAsset(address tokenId, uint256 amount, bool isNative)\n /// @param tokenId Token to deposit\n /// @param amount Amount to deposit\n function depositAsset(address tokenId, uint256 amount) internal {\n return depositAsset(tokenId, amount, tokenId == NATIVE_ASSETID);\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n (assetId == NATIVE_ASSETID)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/common/helpers/BalancesHelperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable-next-line\npragma solidity 0.8.4;\n\n/// @title BalancesHelperV2\n/// @author Luke Wickens \n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\n\nimport {ISuperfluidToken} from \"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/interfaces/IERC20.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\ncontract BalancesHelperV2 {\n using Address for address;\n\n /// @notice Custom errors to handle address(0)\n error AccountZeroAddress(address account, address token);\n error TokenZeroAddress(address account, address token);\n\n constructor() {}\n\n /// @notice Returns balances of accounts for multiple ERC20 tokens.\n /// @dev Error thrown if: account or token address is address(0),\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\n /// @param accounts = Array of accounts addresses\n /// @param tokens = Array of tokens addresses\n /// @return One-dimensional that's accounts.length * tokens.length long. The\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\n\n function getBalances(address[] calldata accounts, address[] calldata tokens)\n external\n view\n returns (uint256[] memory)\n {\n uint256[] memory result = new uint256[](\n accounts.length * tokens.length\n );\n\n for (uint256 i; i < accounts.length; i++) {\n for (uint256 j; j < tokens.length; j++) {\n uint256 index = j + (tokens.length * i);\n result[index] = _getBalance(accounts[i], tokens[j]);\n }\n }\n return result;\n }\n\n /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\n /// @dev Error thrown if: account or token address is address(0),\n /// large arrays of accounts/tokens are passed in could cause gas block limit issue\n /// @param accounts = Array of accounts addresses\n /// @param tokens = Array of tokens addresses\n /// @return One-dimensional that's accounts.length * tokens.length long. The\n /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\n\n function getSuperfluidWrappedTokenBalances(\n address[] calldata accounts,\n address[] calldata tokens\n ) external view returns (int256[] memory) {\n int256[] memory result = new int256[](accounts.length * tokens.length);\n\n for (uint256 i; i < accounts.length; i++) {\n for (uint256 j; j < tokens.length; j++) {\n uint256 index = j + (tokens.length * i);\n result[index] = _getSuperfluidWrappedTokenBalance(\n accounts[i],\n tokens[j]\n );\n }\n }\n return result;\n }\n\n /// Private fuctions\n\n /// @notice Returns balance of account for an ERC20 token.\n /// @dev Error thrown if: account or token address is address(0)\n /// @param account = account address\n /// @param token = tokens address\n /// @return balance of account as uint256.\n\n function _getBalance(address account, address token)\n private\n view\n returns (uint256)\n {\n if (account == address(0)) revert AccountZeroAddress(account, token);\n if (token == address(0)) revert TokenZeroAddress(account, token);\n\n bytes memory returnedData = token.functionStaticCall(\n abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\n );\n\n return abi.decode(returnedData, (uint256));\n }\n\n /// @notice Returns real balance of a user, taking into consideration all agreements of account\n /// @dev Error thrown if: account or token address is address(0)\n /// @param account = account address\n /// @param token = tokens address\n /// @return available balance of account as int256.\n\n function _getSuperfluidWrappedTokenBalance(address account, address token)\n private\n view\n returns (int256)\n {\n if (account == address(0)) revert AccountZeroAddress(account, token);\n if (token == address(0)) revert TokenZeroAddress(account, token);\n\n bytes memory returnedData = token.functionStaticCall(\n abi.encodeWithSelector(\n ISuperfluidToken(token).realtimeBalanceOfNow.selector,\n account\n )\n );\n\n (int256 availableBalance, , , ) = abi.decode(\n returnedData,\n (int256, uint256, uint256, uint256)\n );\n return availableBalance;\n }\n}\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\n// solhint-disable-next-line\npragma solidity 0.8.4;\n\n/// @title CBridgeFacet\n/// @author Luke Wickens \n/// @notice cBridge intergration for bridging tokens\n\nimport {ICBridge} from \"../interfaces/ICBridge.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {ReentrancyGuard} from \"../../common/helpers/DiamondReentrancyGuard.sol\";\nimport {CannotBridgeToSameNetwork, InvalidAmount, InvalidConfig, TokenAddressIsZero, ZeroAddressProvided} from \"../errors/GenericErrors.sol\";\nimport {CBSlippageTooLow} from \"../errors/CBridgeErrors.sol\";\nimport {LibDiamond} from \"../libs/LibDiamond.sol\";\n\ncontract CBridgeFacet is ReentrancyGuard {\n using SafeERC20 for IERC20;\n //////////////////////////////////////////////////////////////\n /////////////////////////// Events ///////////////////////////\n //////////////////////////////////////////////////////////////\n event CBInitialized(address cBridge, uint256 chainId);\n event CBTransferStarted(\n string bridgeUsed,\n address token,\n address from,\n address to,\n uint256 qty,\n uint256 chainIdTo\n );\n event CBUpdatedBridge(address newAddress);\n event CBUpdatedSlippageTolerance(uint256 newSlippage);\n //////////////////////////////////////////////////////////////\n ////////////////////////// Storage ///////////////////////////\n //////////////////////////////////////////////////////////////\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"io.etherspot.facets.cbridge\");\n struct Storage {\n address cbBridge;\n uint256 cbChainId;\n uint32 cbSlippage;\n }\n\n //////////////////////////////////////////////////////////////\n ////////////////////////// Structs ///////////////////////////\n //////////////////////////////////////////////////////////////\n\n struct CBridgeData {\n uint64 dstChainId;\n uint64 nonce;\n uint256 qty;\n address to;\n address token;\n }\n\n /// @notice initializes state variables for the cBridge facet\n /// @param _cbBridge address of the CBridge router contract\n function cbInitialize(address _cbBridge) external {\n LibDiamond.enforceIsContractOwner();\n if (_cbBridge == address(0)) revert ZeroAddressProvided();\n Storage storage s = getStorage();\n s.cbBridge = _cbBridge;\n s.cbChainId = block.chainid;\n s.cbSlippage = 10000; // equates to 1% - has to be > 0.5% (slippage * 1M)\n emit CBInitialized(_cbBridge, block.chainid);\n }\n\n /// @notice initiates token bridging\n /// @param _cbData: provides necessary data for cBridge transfer\n\n function cbBridgeTokens(CBridgeData calldata _cbData)\n external\n payable\n nonReentrant\n {\n if (block.chainid == _cbData.dstChainId)\n revert CannotBridgeToSameNetwork();\n if (_cbData.to == address(0)) revert ZeroAddressProvided();\n if (_cbData.qty <= 0) revert InvalidAmount();\n if (_cbData.token == address(0)) revert TokenAddressIsZero();\n\n Storage storage s = getStorage();\n address bridge = s.cbBridge;\n\n // this contract calls stargate swap()\n IERC20(_cbData.token).safeTransferFrom(\n msg.sender,\n address(this),\n _cbData.qty\n );\n IERC20(_cbData.token).safeApprove(address(bridge), _cbData.qty);\n\n ICBridge(bridge).send(\n _cbData.to,\n _cbData.token,\n _cbData.qty,\n _cbData.dstChainId,\n _cbData.nonce,\n s.cbSlippage\n );\n\n emit CBTransferStarted(\n \"cbridge\",\n _cbData.token,\n msg.sender,\n _cbData.to,\n _cbData.qty,\n _cbData.dstChainId\n );\n }\n\n function cbUpdateSlippageTolerance(uint32 _newSlippage) external {\n // should be > 0.5% (5000)\n if (_newSlippage <= 5000) revert CBSlippageTooLow();\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n s.cbSlippage = _newSlippage;\n emit CBUpdatedSlippageTolerance(_newSlippage);\n }\n\n function cbUpdateBridge(address _newAddress) external {\n LibDiamond.enforceIsContractOwner();\n if (_newAddress == address(0)) revert ZeroAddressProvided();\n Storage storage s = getStorage();\n s.cbBridge = _newAddress;\n emit CBUpdatedBridge(_newAddress);\n }\n\n //////////////////////////////////////////////////////////////\n ////////////////////// Private Functions /////////////////////\n //////////////////////////////////////////////////////////////\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/bridges/interfaces/ICBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable-next-line\npragma solidity 0.8.4;\n\ninterface ICBridge {\n function send(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChinId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external;\n\n function sendNative(\n address _receiver,\n uint256 _amount,\n uint64 _dstChinId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external payable;\n\n function relay(\n bytes calldata _relayRequest,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n}\n" + }, + "src/bridges/errors/CBridgeErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable-next-line\npragma solidity 0.8.4;\n\nerror CBSlippageTooLow();\n" + }, + "src/bridges/facets/HopFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.4;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IHopBridge } from \"../interfaces/IHopBridge.sol\";\nimport { LibAsset } from \"../libs/LibAsset.sol\";\nimport { LibDiamond } from \"../libs/LibDiamond.sol\";\nimport { ReentrancyGuard } from \"../../common/helpers/DiamondReentrancyGuard.sol\";\nimport {\n InvalidAmount,\n InvalidBridgeConfigLength,\n CannotBridgeToSameNetwork,\n NativeValueWithERC,\n InvalidConfig\n} from \"../errors/GenericErrors.sol\";\n\n/**\n * @title Hop Protocol Integration\n *\n * @notice Contract which provides bridging functionality through Hop Protocol\n *\n */\ncontract HopFacet is ReentrancyGuard {\n // storage\n\n bytes32 internal constant NAMESPACE = keccak256(\"io.etherspot.facets.hop\");\n struct Storage {\n uint256 chainLayerId;\n }\n\n // types\n\n struct HopData {\n address bridge;\n address ammWrapper;\n address asset;\n address recipient;\n uint256 chainId;\n uint256 amount;\n uint256 bonderFee;\n uint256 amountOutMin;\n uint256 deadline;\n uint256 destinationAmountOutMin;\n uint256 destinationDeadline;\n }\n\n // events\n\n /**\n * @dev Emitted when facet initializes\n * @param chainId current chain id\n * @param chainLayerId current chain layer id\n */\n event HopInitialized(\n uint256 chainId,\n uint256 chainLayerId\n );\n\n /**\n * @dev Emitted on token swap\n * @param _destination destination chain id\n * @param _bridge address of the bridge on chain _destination,\n * @param _ammWrapper address of the amm wrapper,\n * @param _recipient recipient\n * @param _asset address of the asset\n * @param _amount amount of assets\n * @param _bonderFee fee\n * @param _amountOutMin The minimum amount received after attempting to\n * swap in the destination\n * @param _deadline The deadline for swapping in the destination AMM market.\n * 0 if no * swap is intended.\n * @param _destinationAmountOutMin The minimum amount of tokens to receive after bridging\n * @param _destinationDeadline The time the transaction must be completed\n */\n event HopTokenSwap(\n uint256 indexed _destination,\n address _bridge,\n address _ammWrapper,\n address indexed _recipient,\n address indexed _asset,\n uint256 _amount,\n uint256 _bonderFee,\n uint256 _amountOutMin,\n uint256 _deadline,\n uint256 _destinationAmountOutMin,\n uint256 _destinationDeadline\n );\n\n\n\n // external functions\n\n /**\n * @notice Initializes local variables for the Connext facet\n */\n function initHop(uint256 _chainLayerId) external {\n LibDiamond.enforceIsContractOwner();\n\n Storage storage s = getStorage();\n s.chainLayerId = _chainLayerId;\n\n emit HopInitialized(\n getChainID(),\n _chainLayerId\n );\n }\n\n /**\n * @notice Bridges tokens via Hop Protocol\n * @param _hopData data specific to Hop Protocol\n */\n function hopTokenTransfer(\n HopData calldata _hopData\n ) external payable nonReentrant {\n LibAsset.depositAsset(_hopData.asset, _hopData.amount);\n\n address bridge;\n if (getLayerId() == 1) {\n bridge = _hopData.bridge;\n } else {\n bridge = _hopData.ammWrapper;\n }\n\n if (getChainID() == _hopData.chainId)\n revert CannotBridgeToSameNetwork();\n\n // Give Hop approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(_hopData.asset),\n bridge,\n _hopData.amount\n );\n\n uint256 value = LibAsset.isNativeAsset(_hopData.asset)\n ? _hopData.amount\n : 0;\n\n if (getLayerId() == 1) {\n // Ethereum L1\n IHopBridge(bridge).sendToL2{value: value}(\n _hopData.chainId,\n _hopData.recipient,\n _hopData.amount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n address(0),\n 0\n );\n } else {\n // L2\n IHopBridge(bridge).swapAndSend{value: value}(\n _hopData.chainId,\n _hopData.recipient,\n _hopData.amount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n }\n emit HopTokenSwap(\n _hopData.chainId,\n _hopData.bridge,\n _hopData.ammWrapper,\n _hopData.recipient,\n _hopData.asset,\n _hopData.amount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n }\n\n /// private Methods ///\n\n /**\n * @dev returns local storage\n */\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n\n /**\n * @dev returns current chain layer number\n * @return uint256 layer number\n */\n function getLayerId() private view returns (uint256) {\n return getStorage().chainLayerId;\n }\n\n /**\n * @dev fetch chain id\n */\n function getChainID() private view returns (uint256) {\n uint256 id;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n return id;\n }\n}\n" + }, + "src/bridges/interfaces/IHopBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.4;\n\ninterface IHopBridge {\n function sendToL2(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 amountOutMin,\n uint256 deadline,\n address relayer,\n uint256 relayerFee\n ) external payable;\n\n function swapAndSend(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 deadline,\n uint256 destinationAmountOutMin,\n uint256 destinationDeadline\n ) external payable;\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/neonDevnet/solcInputs/c6bcc786074bb5f47af1ba8ec29021b3.json b/deployments/neonDevnet/solcInputs/c6bcc786074bb5f47af1ba8ec29021b3.json new file mode 100644 index 00000000..d2e0033c --- /dev/null +++ b/deployments/neonDevnet/solcInputs/c6bcc786074bb5f47af1ba8ec29021b3.json @@ -0,0 +1,157 @@ +{ + "language": "Solidity", + "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ł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/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/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/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/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\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 \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\n\n/**\n * @title Gateway V2 with guarded batching functions\n *\n * @notice GSN replacement\n *\n * @author Utkir Sobirov \n */\ncontract GatewayV2 is Initializable, SignatureValidator, Guarded {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct DelegatedBatch {\n address account;\n uint256 nonce;\n address[] to;\n bytes[] data;\n }\n\n struct DelegatedBatchWithGasPrice {\n address account;\n uint256 nonce;\n address[] to;\n bytes[] data;\n uint256 gasPrice;\n }\n\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256(\n \"DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)\"\n );\n\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256(\n \"DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n mapping(address => uint256) private accountNonce;\n\n // events\n\n /**\n * @dev Emitted when the single batch is delegated\n * @param sender sender address\n * @param batch batch\n * @param succeeded if succeeded\n */\n event BatchDelegated(\n address sender,\n bytes batch,\n bool succeeded\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `Gateway` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n\n address[] memory guardians;\n _initializeGuarded(guardians); // adds tx.origin to guardians list\n }\n\n // public functions\n\n /**\n * @notice Sends batch\n * @dev `GatewayRecipient` context api:\n * `_getContextAccount` will return `msg.sender`\n * `_getContextSender` will return `msg.sender`\n *\n * @param to array of batch recipients contracts\n * @param data array of batch data\n */\n function sendBatch(\n address[] memory to,\n bytes[] memory data\n )\n public\n {\n _sendBatch(\n msg.sender,\n msg.sender,\n to,\n data\n );\n }\n\n /**\n * @notice Sends guarded batch\n * @dev `GatewayRecipient` context api:\n * `_getContextAccount` will return `msg.sender`\n * `_getContextSender` will return `msg.sender`\n *\n * @param to array of batch recipients contracts\n * @param data array of batch data\n */\n function sendBatchGuarded(\n address[] memory to,\n bytes[] memory data\n )\n public\n onlyGuardian\n {\n sendBatch(to, data);\n }\n\n /**\n * @notice Sends batch from the account\n * @dev `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return `msg.sender`\n *\n * @param account account address\n * @param to array of batch recipients contracts\n * @param data array of batch data\n */\n function sendBatchFromAccount(\n address account,\n address[] memory to,\n bytes[] memory data\n )\n public\n {\n _sendBatch(\n account,\n msg.sender,\n to,\n data\n );\n }\n\n /**\n * @notice Sends guarded batch from the account\n * @dev `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return `msg.sender`\n *\n * @param account account address\n * @param to array of batch recipients contracts\n * @param data array of batch data\n */\n function sendBatchFromAccountGuarded(\n address account,\n address[] memory to,\n bytes[] memory data\n )\n public\n onlyGuardian\n {\n sendBatchFromAccount(account, to, data);\n }\n\n /**\n * @notice Delegates batch from the account\n * @dev Use `hashDelegatedBatch` to create sender message payload.\n *\n * `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return recovered address from `senderSignature` arg\n *\n * @param account account address\n * @param nonce next account nonce\n * @param to array of batch recipients contracts\n * @param data array of batch data\n * @param senderSignature sender signature\n */\n function delegateBatch(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n bytes memory senderSignature\n )\n public\n {\n require(\n nonce > accountNonce[account],\n \"Gateway: nonce is lower than current account nonce\"\n );\n\n address sender = _hashDelegatedBatch(\n account,\n nonce,\n to,\n data\n ).recoverAddress(senderSignature);\n\n accountNonce[account] = nonce;\n\n _sendBatch(\n account,\n sender,\n to,\n data\n );\n }\n\n /**\n * @notice Delegates guarded batch from the account\n * @dev Use `hashDelegatedBatch` to create sender message payload.\n *\n * `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return recovered address from `senderSignature` arg\n *\n * @param account account address\n * @param nonce next account nonce\n * @param to array of batch recipients contracts\n * @param data array of batch data\n * @param senderSignature sender signature\n */\n function delegateBatchGuarded(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n bytes memory senderSignature\n )\n public\n onlyGuardian\n {\n delegateBatch(account, nonce, to, data, senderSignature);\n }\n\n /**\n * @notice Delegates batch from the account (with gas price)\n *\n * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\n *\n * `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return recovered address from `senderSignature` arg\n *\n * @param account account address\n * @param nonce next account nonce\n * @param to array of batch recipients contracts\n * @param data array of batch data\n * @param senderSignature sender signature\n */\n function delegateBatchWithGasPrice(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n bytes memory senderSignature\n )\n public\n {\n require(\n nonce > accountNonce[account],\n \"Gateway: nonce is lower than current account nonce\"\n );\n\n address sender = _hashDelegatedBatchWithGasPrice(\n account,\n nonce,\n to,\n data,\n tx.gasprice\n ).recoverAddress(senderSignature);\n\n accountNonce[account] = nonce;\n\n _sendBatch(\n account,\n sender,\n to,\n data\n );\n }\n\n /**\n * @notice Delegates guarded batch from the account (with gas price)\n *\n * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\n *\n * `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return recovered address from `senderSignature` arg\n *\n * @param account account address\n * @param nonce next account nonce\n * @param to array of batch recipients contracts\n * @param data array of batch data\n * @param senderSignature sender signature\n */\n function delegateBatchWithGasPriceGuarded(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n bytes memory senderSignature\n )\n public\n onlyGuardian\n {\n delegateBatchWithGasPrice(account, nonce, to, data, senderSignature);\n }\n\n /**\n * @notice Delegates multiple batches\n * @dev It will revert when all batches fail\n * @param batches array of batches\n * @param revertOnFailure reverts on any error\n */\n function delegateBatches(\n bytes[] memory batches,\n bool revertOnFailure\n )\n public\n {\n require(\n batches.length > 0,\n \"Gateway: cannot delegate empty batches\"\n );\n\n bool anySucceeded;\n\n for (uint256 i = 0; i < batches.length; i++) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool succeeded,) = address(this).call(batches[i]);\n\n if (revertOnFailure) {\n require(\n succeeded,\n \"Gateway: batch reverted\"\n );\n } else if (succeeded && !anySucceeded) {\n anySucceeded = true;\n }\n\n emit BatchDelegated(\n msg.sender,\n batches[i],\n succeeded\n );\n }\n\n if (!anySucceeded) {\n revert(\"Gateway: all batches reverted\");\n }\n }\n\n /**\n * @notice Delegates multiple guarded batches\n * @dev It will revert when all batches fail\n * @param batches array of batches\n * @param revertOnFailure reverts on any error\n */\n function delegateBatchesGuarded(\n bytes[] memory batches,\n bool revertOnFailure\n )\n public\n onlyGuardian\n {\n delegateBatches(batches, revertOnFailure);\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DelegatedBatch` message payload\n * @param delegatedBatch struct\n * @return hash\n */\n function hashDelegatedBatch(\n DelegatedBatch memory delegatedBatch\n )\n public\n view\n returns (bytes32)\n {\n return _hashDelegatedBatch(\n delegatedBatch.account,\n delegatedBatch.nonce,\n delegatedBatch.to,\n delegatedBatch.data\n );\n }\n\n /**\n * @notice Hashes `DelegatedBatchWithGasPrice` message payload\n * @param delegatedBatch struct\n * @return hash\n */\n function hashDelegatedBatchWithGasPrice(\n DelegatedBatchWithGasPrice memory delegatedBatch\n )\n public\n view\n returns (bytes32)\n {\n return _hashDelegatedBatchWithGasPrice(\n delegatedBatch.account,\n delegatedBatch.nonce,\n delegatedBatch.to,\n delegatedBatch.data,\n delegatedBatch.gasPrice\n );\n }\n\n // external functions (views)\n\n /**\n * @notice Gets next account nonce\n * @param account account address\n * @return next nonce\n */\n function getAccountNextNonce(\n address account\n )\n external\n view\n returns (uint256)\n {\n return accountNonce[account].add(1);\n }\n\n // private functions\n\n function _sendBatch(\n address account,\n address sender,\n address[] memory to,\n bytes[] memory data\n )\n private\n {\n require(\n account != address(0),\n \"Gateway: cannot send from 0x0 account\"\n );\n require(\n to.length > 0,\n \"Gateway: cannot send empty batch\"\n );\n require(\n data.length == to.length,\n \"Gateway: invalid batch\"\n );\n\n if (account != sender) {\n require(\n personalAccountRegistry.verifyAccountOwner(account, sender) ||\n externalAccountRegistry.verifyAccountOwner(account, sender),\n \"Gateway: sender is not the account owner\"\n );\n }\n\n bool succeeded;\n\n for (uint256 i = 0; i < data.length; i++) {\n require(\n to[i] != address(0),\n \"Gateway: cannot send to 0x0\"\n );\n\n // solhint-disable-next-line avoid-low-level-calls\n (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender));\n\n require(\n succeeded,\n \"Gateway: batch transaction reverted\"\n );\n }\n }\n\n // private functions (views)\n\n function _hashDelegatedBatch(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked(\n account,\n nonce,\n to,\n _concatBytes(data)\n ));\n }\n\n function _hashDelegatedBatchWithGasPrice(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n uint256 gasPrice\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked(\n account,\n nonce,\n to,\n _concatBytes(data),\n gasPrice\n ));\n }\n\n// private functions (pure)\n\n function _concatBytes(bytes[] memory data)\n private\n pure\n returns (bytes memory)\n {\n bytes memory result;\n uint dataLen = data.length;\n\n for (uint i = 0 ; i < dataLen ; i++) {\n result = abi.encodePacked(result, data[i]);\n }\n\n return result;\n }\n}\n" + }, + "src/gateway/Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"../common/libs/ECDSALib.sol\";\nimport \"../common/libs/SafeMathLib.sol\";\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/signature/SignatureValidator.sol\";\nimport \"../external/ExternalAccountRegistry.sol\";\nimport \"../personal/PersonalAccountRegistry.sol\";\n\n\n/**\n * @title Gateway\n *\n * @notice GSN replacement\n *\n * @author Stanisław Głogowski \n */\ncontract Gateway is Initializable, SignatureValidator {\n using ECDSALib for bytes32;\n using SafeMathLib for uint256;\n\n struct DelegatedBatch {\n address account;\n uint256 nonce;\n address[] to;\n bytes[] data;\n }\n\n struct DelegatedBatchWithGasPrice {\n address account;\n uint256 nonce;\n address[] to;\n bytes[] data;\n uint256 gasPrice;\n }\n\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH = keccak256(\n \"DelegatedBatch(address account,uint256 nonce,address[] to,bytes[] data)\"\n );\n\n bytes32 private constant HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE = keccak256(\n \"DelegatedBatchWithGasPrice(address account,uint256 nonce,address[] to,bytes[] data,uint256 gasPrice)\"\n );\n\n ExternalAccountRegistry public externalAccountRegistry;\n PersonalAccountRegistry public personalAccountRegistry;\n\n mapping(address => uint256) private accountNonce;\n\n // events\n\n /**\n * @dev Emitted when the single batch is delegated\n * @param sender sender address\n * @param batch batch\n * @param succeeded if succeeded\n */\n event BatchDelegated(\n address sender,\n bytes batch,\n bool succeeded\n );\n\n /**\n * @dev Public constructor\n */\n constructor() public Initializable() SignatureValidator() {}\n\n // external functions\n\n /**\n * @notice Initializes `Gateway` contract\n * @param externalAccountRegistry_ `ExternalAccountRegistry` contract address\n * @param personalAccountRegistry_ `PersonalAccountRegistry` contract address\n */\n function initialize(\n ExternalAccountRegistry externalAccountRegistry_,\n PersonalAccountRegistry personalAccountRegistry_\n )\n external\n onlyInitializer\n {\n externalAccountRegistry = externalAccountRegistry_;\n personalAccountRegistry = personalAccountRegistry_;\n }\n\n // public functions\n\n /**\n * @notice Sends batch\n * @dev `GatewayRecipient` context api:\n * `_getContextAccount` will return `msg.sender`\n * `_getContextSender` will return `msg.sender`\n *\n * @param to array of batch recipients contracts\n * @param data array of batch data\n */\n function sendBatch(\n address[] memory to,\n bytes[] memory data\n )\n public\n {\n _sendBatch(\n msg.sender,\n msg.sender,\n to,\n data\n );\n }\n\n /**\n * @notice Sends batch from the account\n * @dev `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return `msg.sender`\n *\n * @param account account address\n * @param to array of batch recipients contracts\n * @param data array of batch data\n */\n function sendBatchFromAccount(\n address account,\n address[] memory to,\n bytes[] memory data\n )\n public\n {\n _sendBatch(\n account,\n msg.sender,\n to,\n data\n );\n }\n\n /**\n * @notice Delegates batch from the account\n * @dev Use `hashDelegatedBatch` to create sender message payload.\n *\n * `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return recovered address from `senderSignature` arg\n *\n * @param account account address\n * @param nonce next account nonce\n * @param to array of batch recipients contracts\n * @param data array of batch data\n * @param senderSignature sender signature\n */\n function delegateBatch(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n bytes memory senderSignature\n )\n public\n {\n require(\n nonce > accountNonce[account],\n \"Gateway: nonce is lower than current account nonce\"\n );\n\n address sender = _hashDelegatedBatch(\n account,\n nonce,\n to,\n data\n ).recoverAddress(senderSignature);\n\n accountNonce[account] = nonce;\n\n _sendBatch(\n account,\n sender,\n to,\n data\n );\n }\n\n /**\n * @notice Delegates batch from the account (with gas price)\n *\n * @dev Use `hashDelegatedBatchWithGasPrice` to create sender message payload (tx.gasprice as gasPrice)\n *\n * `GatewayRecipient` context api:\n * `_getContextAccount` will return `account` arg\n * `_getContextSender` will return recovered address from `senderSignature` arg\n *\n * @param account account address\n * @param nonce next account nonce\n * @param to array of batch recipients contracts\n * @param data array of batch data\n * @param senderSignature sender signature\n */\n function delegateBatchWithGasPrice(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n bytes memory senderSignature\n )\n public\n {\n require(\n nonce > accountNonce[account],\n \"Gateway: nonce is lower than current account nonce\"\n );\n\n address sender = _hashDelegatedBatchWithGasPrice(\n account,\n nonce,\n to,\n data,\n tx.gasprice\n ).recoverAddress(senderSignature);\n\n accountNonce[account] = nonce;\n\n _sendBatch(\n account,\n sender,\n to,\n data\n );\n }\n\n /**\n * @notice Delegates multiple batches\n * @dev It will revert when all batches fail\n * @param batches array of batches\n * @param revertOnFailure reverts on any error\n */\n function delegateBatches(\n bytes[] memory batches,\n bool revertOnFailure\n )\n public\n {\n require(\n batches.length > 0,\n \"Gateway: cannot delegate empty batches\"\n );\n\n bool anySucceeded;\n\n for (uint256 i = 0; i < batches.length; i++) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool succeeded,) = address(this).call(batches[i]);\n\n if (revertOnFailure) {\n require(\n succeeded,\n \"Gateway: batch reverted\"\n );\n } else if (succeeded && !anySucceeded) {\n anySucceeded = true;\n }\n\n emit BatchDelegated(\n msg.sender,\n batches[i],\n succeeded\n );\n }\n\n if (!anySucceeded) {\n revert(\"Gateway: all batches reverted\");\n }\n }\n\n // public functions (views)\n\n /**\n * @notice Hashes `DelegatedBatch` message payload\n * @param delegatedBatch struct\n * @return hash\n */\n function hashDelegatedBatch(\n DelegatedBatch memory delegatedBatch\n )\n public\n view\n returns (bytes32)\n {\n return _hashDelegatedBatch(\n delegatedBatch.account,\n delegatedBatch.nonce,\n delegatedBatch.to,\n delegatedBatch.data\n );\n }\n\n /**\n * @notice Hashes `DelegatedBatchWithGasPrice` message payload\n * @param delegatedBatch struct\n * @return hash\n */\n function hashDelegatedBatchWithGasPrice(\n DelegatedBatchWithGasPrice memory delegatedBatch\n )\n public\n view\n returns (bytes32)\n {\n return _hashDelegatedBatchWithGasPrice(\n delegatedBatch.account,\n delegatedBatch.nonce,\n delegatedBatch.to,\n delegatedBatch.data,\n delegatedBatch.gasPrice\n );\n }\n\n // external functions (views)\n\n /**\n * @notice Gets next account nonce\n * @param account account address\n * @return next nonce\n */\n function getAccountNextNonce(\n address account\n )\n external\n view\n returns (uint256)\n {\n return accountNonce[account].add(1);\n }\n\n // private functions\n\n function _sendBatch(\n address account,\n address sender,\n address[] memory to,\n bytes[] memory data\n )\n private\n {\n require(\n account != address(0),\n \"Gateway: cannot send from 0x0 account\"\n );\n require(\n to.length > 0,\n \"Gateway: cannot send empty batch\"\n );\n require(\n data.length == to.length,\n \"Gateway: invalid batch\"\n );\n\n if (account != sender) {\n require(\n personalAccountRegistry.verifyAccountOwner(account, sender) ||\n externalAccountRegistry.verifyAccountOwner(account, sender),\n \"Gateway: sender is not the account owner\"\n );\n }\n\n bool succeeded;\n\n for (uint256 i = 0; i < data.length; i++) {\n require(\n to[i] != address(0),\n \"Gateway: cannot send to 0x0\"\n );\n\n // solhint-disable-next-line avoid-low-level-calls\n (succeeded,) = to[i].call(abi.encodePacked(data[i], account, sender));\n\n require(\n succeeded,\n \"Gateway: batch transaction reverted\"\n );\n }\n }\n\n // private functions (views)\n\n function _hashDelegatedBatch(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH, abi.encodePacked(\n account,\n nonce,\n to,\n _concatBytes(data)\n ));\n }\n\n function _hashDelegatedBatchWithGasPrice(\n address account,\n uint256 nonce,\n address[] memory to,\n bytes[] memory data,\n uint256 gasPrice\n )\n private\n view\n returns (bytes32)\n {\n return _hashMessagePayload(HASH_PREFIX_DELEGATED_BATCH_WITH_GAS_PRICE, abi.encodePacked(\n account,\n nonce,\n to,\n _concatBytes(data),\n gasPrice\n ));\n }\n\n// private functions (pure)\n\n function _concatBytes(bytes[] memory data)\n private\n pure\n returns (bytes memory)\n {\n bytes memory result;\n uint dataLen = data.length;\n\n for (uint i = 0 ; i < dataLen ; i++) {\n result = abi.encodePacked(result, data[i]);\n }\n\n return result;\n }\n}" + }, + "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" + }, + "src/common/account/mocks/AccountRegistryMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../../libs/ECDSALib.sol\";\nimport \"../../libs/ECDSAExtendedLib.sol\";\nimport \"../AccountRegistry.sol\";\n\n\n/**\n * @title Account registry mock\n *\n * @author Stanisław Głogowski \n */\ncontract AccountRegistryMock is AccountRegistry {\n using ECDSALib for bytes32;\n using ECDSAExtendedLib for bytes;\n\n mapping(address => mapping(address => bool)) private mockedAccountsOwners;\n\n // external functions\n\n function mockAccountOwners(\n address account,\n address[] memory owners\n )\n external\n {\n uint ownersLen = owners.length;\n for (uint i = 0; i < ownersLen; i++) {\n mockedAccountsOwners[account][owners[i]] = true;\n }\n }\n\n // external functions (views)\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 address recovered = messageHash.recoverAddress(signature);\n\n return mockedAccountsOwners[account][recovered];\n }\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 address recovered = message.toEthereumSignedMessageHash().recoverAddress(signature);\n\n return mockedAccountsOwners[account][recovered];\n }\n}\n" + }, + "src/common/access/mocks/GuardedMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../Guarded.sol\";\n\n\n/**\n * @title Guarded mock\n *\n * @dev Used in `Guarded` contract tests\n *\n * @author Stanisław Głogowski \n */\ncontract GuardedMock is Guarded {\n /**\n * @dev Public constructor\n * @param guardians_ array of guardians addresses\n */\n constructor(\n address[] memory guardians_\n )\n public\n {\n _initializeGuarded(guardians_);\n }\n}\n" + }, + "src/common/account/mocks/AccountControllerMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../AccountController.sol\";\n\n\n/**\n * @title Account controller mock\n *\n * @author Stanisław Głogowski \n */\ncontract AccountControllerMock is AccountController {\n /**\n * @dev Public constructor\n * @param accountRegistry_ account registry address\n * @param accountImplementation_ account implementation address\n */\n constructor(\n address accountRegistry_,\n address accountImplementation_\n )\n public\n AccountController()\n {\n _initializeAccountController(accountRegistry_, accountImplementation_);\n }\n\n // external functions\n\n /**\n * @notice Sets account registry\n * @param accountRegistry_ account registry address\n */\n function setAccountRegistry(\n address accountRegistry_\n )\n external\n {\n _setAccountRegistry(accountRegistry_, true);\n }\n\n /**\n * @notice Sets account implementation\n * @param accountImplementation_ account implementation address\n */\n function setAccountImplementation(\n address accountImplementation_\n )\n external\n {\n _setAccountImplementation(accountImplementation_, true);\n }\n\n /**\n * @notice Deploys account\n * @param salt CREATE2 salt\n */\n function deployAccount(\n bytes32 salt\n )\n external\n {\n _deployAccount(salt, true);\n }\n\n /**\n * @notice Upgrades account\n * @param account account address\n */\n function upgradeAccount(\n address account\n )\n external\n {\n _upgradeAccount(account, true);\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 */\n function executeAccountTransaction(\n address account,\n address to,\n uint256 value,\n bytes memory data\n )\n external\n {\n _executeAccountTransaction(account, to, value, data, true);\n }\n\n // external 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 external\n view\n returns (address)\n {\n return _computeAccountAddress(salt);\n }\n}\n" + }, + "src/common/helpers/BalancesHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../token/ERC20Token.sol\";\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title Balances helper\n *\n * @author Jegor Sidorenko \n * @author Stanisław Głogowski \n */\ncontract BalancesHelper {\n using SafeMathLib for uint256;\n\n // external functions\n\n /**\n * @notice Checks the token balances of accounts for multiple tokens.\n * @dev Pass 0x0 as a \"token\" address to get ETH balance.\n *\n * Possible error throws:\n * - extremely large arrays for account and or tokens (gas cost too high)\n *\n * @param accounts array of accounts addresses\n * @param tokens array of tokens addresses\n * @return a one-dimensional that's user.length * tokens.length long. The\n * array is ordered by all of the 0th accounts token balances, then the 1th\n * user, and so on.\n */\n function getBalances(\n address[] calldata accounts,\n address[] calldata tokens\n )\n external\n view\n returns (uint[] memory)\n {\n uint[] memory result = new uint[](accounts.length.mul(tokens.length));\n\n for (uint i = 0; i < accounts.length; i++) {\n for (uint j = 0; j < tokens.length; j++) {\n uint index = j.add(tokens.length.mul(i));\n\n if (tokens[j] != address(0x0)) {\n result[index] = _getBalance(accounts[i], tokens[j]);\n } else {\n result[index] = accounts[i].balance;\n }\n }\n }\n\n return result;\n }\n\n // private functions\n\n function _getBalance(\n address account,\n address token\n )\n private\n view\n returns (uint256)\n {\n uint256 result = 0;\n uint256 tokenCode;\n\n /// @dev check if token is actually a contract\n // solhint-disable-next-line no-inline-assembly\n assembly { tokenCode := extcodesize(token) } // contract code size\n\n if (tokenCode > 0) {\n /// @dev is it a contract and does it implement balanceOf\n // solhint-disable-next-line avoid-low-level-calls\n (bool methodExists,) = token.staticcall(abi.encodeWithSelector(\n ERC20Token(token).balanceOf.selector,\n account\n ));\n\n if (methodExists) {\n result = ERC20Token(token).balanceOf(account);\n }\n }\n\n return result;\n }\n}\n" + }, + "src/gateway/mocks/GatewayRecipientMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../GatewayRecipient.sol\";\n\n\n/**\n * @title Gateway recipient mock\n *\n * @dev Used in `GatewayRecipient` contract tests\n *\n * @author Stanisław Głogowski \n */\ncontract GatewayRecipientMock is GatewayRecipient {\n // events\n\n event Context(\n address account,\n address sender,\n bytes data\n );\n\n /**\n * @dev Public constructor\n * @param gateway_ `Gateway` contract address\n */\n constructor(\n address gateway_\n )\n public\n {\n _initializeGatewayRecipient(gateway_);\n }\n\n function emitContext()\n external\n {\n emit Context(\n _getContextAccount(),\n _getContextSender(),\n _getContextData()\n );\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