From ed0424563a5defc821da537efa43440d5fc82b3d Mon Sep 17 00:00:00 2001 From: 0xKoiner Date: Tue, 16 Dec 2025 18:12:06 +0100 Subject: [PATCH] (benchmarks) Openfort 7702 Account Benchmark --- snapshots/BenchmarkTest.json | 102 +++-- test/Benchmark.t.sol | 359 +++++++++++++++ .../utils/interfaces/IERC4337EntryPointV8.sol | 431 ++++++++++++++++++ test/utils/interfaces/IPimlicoPaymaster.sol | 62 +++ 4 files changed, 907 insertions(+), 47 deletions(-) create mode 100644 test/utils/interfaces/IERC4337EntryPointV8.sol diff --git a/snapshots/BenchmarkTest.json b/snapshots/BenchmarkTest.json index 82f7d2ae..98bb6a7a 100644 --- a/snapshots/BenchmarkTest.json +++ b/snapshots/BenchmarkTest.json @@ -1,53 +1,61 @@ { - "testERC20Transfer_AlchemyModularAccount": "179494", - "testERC20Transfer_AlchemyModularAccount_AppSponsor": "176436", - "testERC20Transfer_AlchemyModularAccount_ERC20SelfPay": "207779", - "testERC20Transfer_Batch100_AlchemyModularAccount_AppSponsor": "8897167", - "testERC20Transfer_Batch100_CoinbaseSmartWallet": "9952203", - "testERC20Transfer_Batch100_CoinbaseSmartWallet_AppSponsor": "8787327", - "testERC20Transfer_Batch100_CoinbaseSmartWallet_ERC20SelfPay": "11335605", - "testERC20Transfer_Batch100_Safe4337": "11685484", - "testERC20Transfer_Batch100_Safe4337_AppSponsor": "10198375", - "testERC20Transfer_Batch100_Safe4337_ERC20SelfPay": "12757523", - "testERC20Transfer_Batch100_ZerodevKernel_AppSponsor": "11427583", - "testERC20Transfer_CoinbaseSmartWallet": "177855", - "testERC20Transfer_CoinbaseSmartWallet_AppSponsor": "175259", - "testERC20Transfer_CoinbaseSmartWallet_ERC20SelfPay": "204919", - "testERC20Transfer_ERC4337MinimalAccount": "171509", - "testERC20Transfer_ERC4337MinimalAccount_AppSponsor": "168500", - "testERC20Transfer_ERC4337MinimalAccount_ERC20SelfPay": "199831", - "testERC20Transfer_IthacaAccount": "128195", - "testERC20Transfer_IthacaAccountWithSpendLimits": "193658", - "testERC20Transfer_IthacaAccount_AppSponsor": "138709", - "testERC20Transfer_IthacaAccount_AppSponsor_ERC20": "144010", - "testERC20Transfer_IthacaAccount_ERC20SelfPay": "128684", - "testERC20Transfer_Safe4337": "197561", - "testERC20Transfer_Safe4337_AppSponsor": "191725", - "testERC20Transfer_Safe4337_ERC20SelfPay": "221464", - "testERC20Transfer_ZerodevKernel": "207117", - "testERC20Transfer_ZerodevKernel_AppSponsor": "204120", - "testERC20Transfer_ZerodevKernel_ERC20SelfPay": "235489", - "testERC20Transfer_batch100_AlchemyModularAccount": "10109066", - "testERC20Transfer_batch100_AlchemyModularAccount_ERC20SelfPay": "11609298", - "testERC20Transfer_batch100_IthacaAccount": "7545392", - "testERC20Transfer_batch100_IthacaAccount_AppSponsor": "8151496", - "testERC20Transfer_batch100_IthacaAccount_AppSponsor_ERC20": "7977508", - "testERC20Transfer_batch100_IthacaAccount_ERC20SelfPay": "7366652", - "testERC20Transfer_batch100_ZerodevKernel": "12631318", - "testERC20Transfer_batch100_ZerodevKernel_ERC20SelfPay": "14149937", + "testERC20Transfer_AlchemyModularAccount": "179448", + "testERC20Transfer_AlchemyModularAccount_AppSponsor": "176390", + "testERC20Transfer_AlchemyModularAccount_ERC20SelfPay": "207873", + "testERC20Transfer_Batch100_AlchemyModularAccount_AppSponsor": "8892567", + "testERC20Transfer_Batch100_CoinbaseSmartWallet": "9947603", + "testERC20Transfer_Batch100_CoinbaseSmartWallet_AppSponsor": "8782727", + "testERC20Transfer_Batch100_CoinbaseSmartWallet_ERC20SelfPay": "11345005", + "testERC20Transfer_Batch100_Openfort": "11835358", + "testERC20Transfer_Batch100_Openfort_AppSponsor": "10594273", + "testERC20Transfer_Batch100_Openfort_ERC20SelfPay": "12862680", + "testERC20Transfer_Batch100_Safe4337": "11680884", + "testERC20Transfer_Batch100_Safe4337_AppSponsor": "10193775", + "testERC20Transfer_Batch100_Safe4337_ERC20SelfPay": "12766923", + "testERC20Transfer_Batch100_ZerodevKernel_AppSponsor": "11422983", + "testERC20Transfer_CoinbaseSmartWallet": "177809", + "testERC20Transfer_CoinbaseSmartWallet_AppSponsor": "175213", + "testERC20Transfer_CoinbaseSmartWallet_ERC20SelfPay": "205013", + "testERC20Transfer_ERC4337MinimalAccount": "171894", + "testERC20Transfer_ERC4337MinimalAccount_AppSponsor": "168893", + "testERC20Transfer_ERC4337MinimalAccount_ERC20SelfPay": "200388", + "testERC20Transfer_IthacaAccount": "129918", + "testERC20Transfer_IthacaAccountWithSpendLimits": "190799", + "testERC20Transfer_IthacaAccount_AppSponsor": "141374", + "testERC20Transfer_IthacaAccount_AppSponsor_ERC20": "146727", + "testERC20Transfer_IthacaAccount_ERC20SelfPay": "130471", + "testERC20Transfer_Openfort": "175382", + "testERC20Transfer_Openfort_AppSponsor": "172087", + "testERC20Transfer_Openfort_ERC20SelfPay": "199404", + "testERC20Transfer_Safe4337": "197515", + "testERC20Transfer_Safe4337_AppSponsor": "191679", + "testERC20Transfer_Safe4337_ERC20SelfPay": "221558", + "testERC20Transfer_ZerodevKernel": "207071", + "testERC20Transfer_ZerodevKernel_AppSponsor": "204074", + "testERC20Transfer_ZerodevKernel_ERC20SelfPay": "235583", + "testERC20Transfer_batch100_AlchemyModularAccount": "10104466", + "testERC20Transfer_batch100_AlchemyModularAccount_ERC20SelfPay": "11618698", + "testERC20Transfer_batch100_IthacaAccount": "7695676", + "testERC20Transfer_batch100_IthacaAccount_AppSponsor": "8394972", + "testERC20Transfer_batch100_IthacaAccount_AppSponsor_ERC20": "8227156", + "testERC20Transfer_batch100_IthacaAccount_ERC20SelfPay": "7523336", + "testERC20Transfer_batch100_ZerodevKernel": "12626718", + "testERC20Transfer_batch100_ZerodevKernel_ERC20SelfPay": "14159337", "testNativeTransfer_AlchemyModularAccount": "180829", "testNativeTransfer_CoinbaseSmartWallet": "178916", - "testNativeTransfer_IthacaAccount": "129551", - "testNativeTransfer_IthacaAccount_AppSponsor": "140096", - "testNativeTransfer_IthacaAccount_ERC20SelfPay": "137340", + "testNativeTransfer_IthacaAccount": "131320", + "testNativeTransfer_IthacaAccount_AppSponsor": "142783", + "testNativeTransfer_IthacaAccount_ERC20SelfPay": "139173", + "testNativeTransfer_Openfort": "176555", "testNativeTransfer_Safe4337": "198595", "testNativeTransfer_ZerodevKernel": "208635", - "testUniswapV2Swap_AlchemyModularAccount": "238647", - "testUniswapV2Swap_CoinbaseSmartWallet": "237451", - "testUniswapV2Swap_ERC4337MinimalAccount": "230691", - "testUniswapV2Swap_IthacaAccount": "187339", - "testUniswapV2Swap_IthacaAccount_AppSponsor": "197817", - "testUniswapV2Swap_IthacaAccount_ERC20SelfPay": "192628", - "testUniswapV2Swap_Safe4337": "257333", - "testUniswapV2Swap_ZerodevKernel": "266367" + "testUniswapV2Swap_AlchemyModularAccount": "238767", + "testUniswapV2Swap_CoinbaseSmartWallet": "237571", + "testUniswapV2Swap_ERC4337MinimalAccount": "231242", + "testUniswapV2Swap_IthacaAccount": "189228", + "testUniswapV2Swap_IthacaAccount_AppSponsor": "200636", + "testUniswapV2Swap_IthacaAccount_ERC20SelfPay": "194581", + "testUniswapV2Swap_Openfort": "234662", + "testUniswapV2Swap_Safe4337": "257453", + "testUniswapV2Swap_ZerodevKernel": "266487" } \ No newline at end of file diff --git a/test/Benchmark.t.sol b/test/Benchmark.t.sol index 2ce04524..ffeb5824 100644 --- a/test/Benchmark.t.sol +++ b/test/Benchmark.t.sol @@ -6,6 +6,7 @@ import "./Base.t.sol"; import "./utils/interfaces/IERC4337EntryPoint.sol"; import "./utils/mocks/MockMinimalAccount.sol"; import "./utils/mocks/MockMinimalOrchestrator.sol"; +import {IEntryPoint as IEntryPointV8, PackedUserOperation as PackedUserOperationV8} from "test/utils/interfaces/IERC4337EntryPointV8.sol"; import {MockERC4337Account, ERC4337} from "./utils/mocks/MockERC4337Account.sol"; import {SignatureCheckerLib} from "solady/utils/SignatureCheckerLib.sol"; import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; @@ -44,6 +45,7 @@ contract BenchmarkTest is BaseTest { address constant _ERC4337_ENTRYPOINT_V06_ADDR = 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789; address constant _ERC4337_ENTRYPOINT_ADDR = 0x0000000071727De22E5E9d8BAf0edAc6f37da032; + address constant _ERC4337_ENTRYPOINT_V08_ADDR = 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108; address constant _UNISWAP_V2_FACTORY_ADDRESS = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; address constant _UNISWAP_V2_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; @@ -66,8 +68,12 @@ contract BenchmarkTest is BaseTest { address constant _SAFE_4337_MODULE = 0xa581c4A4DB7175302464fF3C06380BC3270b4037; address constant _ADD_MODULES_LIB = 0x8EcD4ec46D4D2a6B64fE960B3D64e8B94B2234eb; + address constant _OPF7702 = 0x7702080183EE36Ef64F317815185D89BFc6B239A; + address constant _PIMLICO_PAYMASTER_V06 = 0x6666666666667849c56f2850848cE1C4da65c68b; address constant _PIMLICO_PAYMASTER_V07 = 0x777777777777AeC03fd955926DbF81597e66834C; + address constant _PIMLICO_PAYMASTER_V08 = 0x888888888888Ec68A58AB8094Cc1AD20Ba3D2402; + address paymasterSigner; uint256 paymasterPrivateKey; @@ -76,6 +82,7 @@ contract BenchmarkTest is BaseTest { IERC4337EntryPointV6 public erc4337EntryPointV6 = IERC4337EntryPointV6(_ERC4337_ENTRYPOINT_V06_ADDR); IERC4337EntryPoint erc4337EntryPoint = IERC4337EntryPoint(_ERC4337_ENTRYPOINT_ADDR); + IEntryPointV8 erc4337EntryPointV8 = IEntryPointV8(_ERC4337_ENTRYPOINT_V08_ADDR); ERC4337 erc4337Account; address coinbaseSmartAccount; address kernel; @@ -123,6 +130,9 @@ contract BenchmarkTest is BaseTest { IStakeManager(_ERC4337_ENTRYPOINT_V06_ADDR) .depositTo{value: 1 ether}(_PIMLICO_PAYMASTER_V06); IStakeManager(_ERC4337_ENTRYPOINT_ADDR).depositTo{value: 1 ether}(_PIMLICO_PAYMASTER_V07); + IStakeManager(_ERC4337_ENTRYPOINT_V08_ADDR).depositTo{value: 1 ether}( + _PIMLICO_PAYMASTER_V08 + ); (paymasterSigner, paymasterPrivateKey) = makeAddrAndKey(""); @@ -132,6 +142,9 @@ contract BenchmarkTest is BaseTest { stdstore.target(_PIMLICO_PAYMASTER_V07).sig(IPimlicoPaymaster.signers.selector) .with_key(paymasterSigner).checked_write(true); + stdstore.target(_PIMLICO_PAYMASTER_V08).sig(IPimlicoPaymaster.signers.selector) + .with_key(paymasterSigner).checked_write(true); + _giveAccountSomeTokens(relayer); // Set up app sponsor for APP_SPONSOR payment type @@ -165,6 +178,10 @@ contract BenchmarkTest is BaseTest { _ERC4337_ENTRYPOINT_ADDR, hex"60806040526004361015610024575b361561001957600080fd5b61002233612748565b005b60003560e01c806242dc5314611b0057806301ffc9a7146119ae5780630396cb60146116765780630bd28e3b146115fa5780631b2e01b814611566578063205c2878146113d157806322cdde4c1461136b57806335567e1a146112b35780635287ce12146111a557806370a0823114611140578063765e827f14610e82578063850aaf6214610dc35780639b249f6914610c74578063b760faf914610c3a578063bb9fe6bf14610a68578063c23a5cea146107c4578063dbed18e0146101a15763fc7e286d0361000e573461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61013a61229f565b16600052600060205260a0604060002065ffffffffffff6001825492015460405192835260ff8116151560208401526dffffffffffffffffffffffffffff8160081c16604084015263ffffffff8160781c16606084015260981c166080820152f35b600080fd5b3461019c576101af36612317565b906101b86129bd565b60009160005b82811061056f57506101d08493612588565b6000805b8481106102fc5750507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000809360005b81811061024757610240868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2613ba7565b6001600255005b6102a261025582848a612796565b73ffffffffffffffffffffffffffffffffffffffff6102766020830161282a565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a2806127d6565b906000915b8083106102b957505050600101610209565b909194976102f36102ed6001926102e78c8b6102e0826102da8e8b8d61269d565b9261265a565b5191613597565b90612409565b99612416565b950191906102a7565b6020610309828789612796565b61031f61031682806127d6565b9390920161282a565b9160009273ffffffffffffffffffffffffffffffffffffffff8091165b8285106103505750505050506001016101d4565b909192939561037f83610378610366848c61265a565b516103728b898b61269d565b856129f6565b9290613dd7565b9116840361050a576104a5576103958491613dd7565b9116610440576103b5576103aa600191612416565b96019392919061033c565b60a487604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b61057a818487612796565b9361058585806127d6565b919095602073ffffffffffffffffffffffffffffffffffffffff6105aa82840161282a565b1697600192838a1461076657896105da575b5050505060019293949550906105d191612409565b939291016101be565b8060406105e892019061284b565b918a3b1561019c57929391906040519485937f2dd8113300000000000000000000000000000000000000000000000000000000855288604486016040600488015252606490818601918a60051b8701019680936000915b8c83106106e657505050505050838392610684927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8560009803016024860152612709565b03818a5afa90816106d7575b506106c657602486604051907f86a9f7500000000000000000000000000000000000000000000000000000000082526004820152fd5b93945084936105d1600189806105bc565b6106e0906121bd565b88610690565b91939596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c908a9294969a0301865288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181121561019c57836107538793858394016128ec565b9a0196019301909189979695949261063f565b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b3461019c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576107fc61229f565b33600052600082526001604060002001908154916dffffffffffffffffffffffffffff8360081c16928315610a0a5765ffffffffffff8160981c1680156109ac57421061094e5760009373ffffffffffffffffffffffffffffffffffffffff859485947fffffffffffffff000000000000000000000000000000000000000000000000ff86951690556040517fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda33391806108da8786836020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0390a2165af16108e8612450565b50156108f057005b606490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b3461019c5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c573360005260006020526001604060002001805463ffffffff8160781c16908115610bdc5760ff1615610b7e5765ffffffffffff908142160191818311610b4f5780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609885901b161790556040519116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a2005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610022610c6f61229f565b612748565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043567ffffffffffffffff811161019c576020610cc8610d1b9236906004016122c2565b919073ffffffffffffffffffffffffffffffffffffffff9260405194859283927f570e1a360000000000000000000000000000000000000000000000000000000084528560048501526024840191612709565b03816000857f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c165af1908115610db757602492600092610d86575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b610da991925060203d602011610db0575b610da181836121ed565b8101906126dd565b9083610d56565b503d610d97565b6040513d6000823e3d90fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610dfa61229f565b60243567ffffffffffffffff811161019c57600091610e1e839236906004016122c2565b90816040519283928337810184815203915af4610e39612450565b90610e7e6040519283927f99410554000000000000000000000000000000000000000000000000000000008452151560048401526040602484015260448301906123c6565b0390fd5b3461019c57610e9036612317565b610e9b9291926129bd565b610ea483612588565b60005b848110610f1c57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000915b858310610eec576102408585613ba7565b909193600190610f12610f0087898761269d565b610f0a888661265a565b519088613597565b0194019190610edb565b610f47610f40610f2e8385979561265a565b51610f3a84898761269d565b846129f6565b9190613dd7565b73ffffffffffffffffffffffffffffffffffffffff929183166110db5761107657610f7190613dd7565b911661101157610f8657600101929092610ea7565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61118c61229f565b1660005260006020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff6111f161229f565b6000608060405161120181612155565b828152826020820152826040820152826060820152015216600052600060205260a06040600020608060405161123681612155565b6001835493848352015490602081019060ff8316151582526dffffffffffffffffffffffffffff60408201818560081c16815263ffffffff936060840193858760781c16855265ffffffffffff978891019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760206112ec61229f565b73ffffffffffffffffffffffffffffffffffffffff6113096122f0565b911660005260018252604060002077ffffffffffffffffffffffffffffffffffffffffffffffff821660005282526040600020547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b3461019c577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60208136011261019c576004359067ffffffffffffffff821161019c5761012090823603011261019c576113c9602091600401612480565b604051908152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761140861229f565b60243590336000526000602052604060002090815491828411611508576000808573ffffffffffffffffffffffffffffffffffffffff8295839561144c848a612443565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af16114a2612450565b50156114aa57005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761159d61229f565b73ffffffffffffffffffffffffffffffffffffffff6115ba6122f0565b9116600052600160205277ffffffffffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043577ffffffffffffffffffffffffffffffffffffffffffffffff811680910361019c5733600052600160205260406000209060005260205260406000206116728154612416565b9055005b6020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043563ffffffff9182821680920361019c5733600052600081526040600020928215611950576001840154908160781c1683106118f2576116f86dffffffffffffffffffffffffffff9182349160081c16612409565b93841561189457818511611836579065ffffffffffff61180592546040519061172082612155565b8152848101926001845260408201908816815260608201878152600160808401936000855233600052600089526040600020905181550194511515917fffffffffffffffffffffffffff0000000000000000000000000000000000000060ff72ffffffff0000000000000000000000000000006effffffffffffffffffffffffffff008954945160081b16945160781b1694169116171717835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b6040519283528201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a2005b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019c57807f60fc6b6e0000000000000000000000000000000000000000000000000000000060209214908115611ad6575b8115611aac575b8115611a82575b8115611a58575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482611a4d565b7f3e84f0210000000000000000000000000000000000000000000000000000000081149150611a46565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150611a3f565b7f915074d80000000000000000000000000000000000000000000000000000000081149150611a38565b3461019c576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5767ffffffffffffffff60043581811161019c573660238201121561019c57611b62903690602481600401359101612268565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c0811261019c5761014060405191611b9e83612155565b1261019c5760405192611bb0846121a0565b60243573ffffffffffffffffffffffffffffffffffffffff8116810361019c578452602093604435858201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff8116810361019c5760e08201526101243561010082015261014435610120820152825261016435848301526101843560408301526101a43560608301526101c43560808301526101e43590811161019c57611c7c9036906004016122c2565b905a3033036120f7578351606081015195603f5a0260061c61271060a0840151890101116120ce5760009681519182611ff0575b5050505090611cca915a9003608085015101923691612268565b925a90600094845193611cdc85613ccc565b9173ffffffffffffffffffffffffffffffffffffffff60e0870151168015600014611ea957505073ffffffffffffffffffffffffffffffffffffffff855116935b5a9003019360a06060820151910151016080860151850390818111611e95575b50508302604085015192818410600014611dce5750506003811015611da157600203611d79576113c99293508093611d7481613d65565b613cf6565b5050507fdeadaa51000000000000000000000000000000000000000000000000000000008152fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b81611dde92979396940390613c98565b506003841015611e6857507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f60808683015192519473ffffffffffffffffffffffffffffffffffffffff865116948873ffffffffffffffffffffffffffffffffffffffff60e0890151169701519160405192835215898301528760408301526060820152a46113c9565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b6064919003600a0204909301928780611d3d565b8095918051611eba575b5050611d1d565b6003861015611fc1576002860315611eb35760a088015190823b1561019c57600091611f2491836040519586809581947f7c627b210000000000000000000000000000000000000000000000000000000083528d60048401526080602484015260848301906123c6565b8b8b0260448301528b60648301520393f19081611fad575b50611fa65787893d610800808211611f9e575b506040519282828501016040528184528284013e610e7e6040519283927fad7954bc000000000000000000000000000000000000000000000000000000008452600484015260248301906123c6565b905083611f4f565b8980611eb3565b611fb89199506121bd565b6000978a611f3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91600092918380938c73ffffffffffffffffffffffffffffffffffffffff885116910192f115612023575b808080611cb0565b611cca929195503d6108008082116120c6575b5060405190888183010160405280825260008983013e805161205f575b5050600194909161201b565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20188870151918973ffffffffffffffffffffffffffffffffffffffff8551169401516120bc604051928392835260408d84015260408301906123c6565b0390a38680612053565b905088612036565b877fdeaddead000000000000000000000000000000000000000000000000000000006000526000fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff82111761217157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610140810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157604052565b6060810190811067ffffffffffffffff82111761217157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926122748261222e565b9161228260405193846121ed565b82948184528183011161019c578281602093846000960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9181601f8401121561019c5782359167ffffffffffffffff831161019c576020838186019501011161019c57565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261019c5760043567ffffffffffffffff9283821161019c578060238301121561019c57816004013593841161019c5760248460051b8301011161019c57602401919060243573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b60005b8381106123b65750506000910152565b81810151838201526020016123a6565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093612402815180928187528780880191016123a3565b0116010190565b91908201809211610b4f57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610b4f5760010190565b91908203918211610b4f57565b3d1561247b573d906124618261222e565b9161246f60405193846121ed565b82523d6000602084013e565b606090565b604061248e8183018361284b565b90818351918237206124a3606084018461284b565b90818451918237209260c06124bb60e083018361284b565b908186519182372091845195602087019473ffffffffffffffffffffffffffffffffffffffff833516865260208301358789015260608801526080870152608081013560a087015260a081013582870152013560e08501526101009081850152835261012083019167ffffffffffffffff918484108385111761217157838252845190206101408501908152306101608601524661018086015260608452936101a00191821183831017612171575251902090565b67ffffffffffffffff81116121715760051b60200190565b9061259282612570565b6040906125a260405191826121ed565b8381527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06125d08295612570565b019160005b8381106125e25750505050565b60209082516125f081612155565b83516125fb816121a0565b600081526000849181838201528187820152816060818184015260809282848201528260a08201528260c08201528260e082015282610100820152826101208201528652818587015281898701528501528301528286010152016125d5565b805182101561266e5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919081101561266e5760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18136030182121561019c570190565b9081602091031261019c575173ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61278a3485613c98565b936040519485521692a2565b919081101561266e5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561019c570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c57602001918160051b3603831361019c57565b3573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c5760200191813603831361019c57565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561019c57016020813591019167ffffffffffffffff821161019c57813603831361019c57565b61012091813573ffffffffffffffffffffffffffffffffffffffff811680910361019c576129626129476129ba9561299b93855260208601356020860152612937604087018761289c565b9091806040880152860191612709565b612954606086018661289c565b908583036060870152612709565b6080840135608084015260a084013560a084015260c084013560c084015261298d60e085018561289c565b9084830360e0860152612709565b916129ac610100918281019061289c565b929091818503910152612709565b90565b60028054146129cc5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b926000905a93805194843573ffffffffffffffffffffffffffffffffffffffff811680910361019c5786526020850135602087015260808501356fffffffffffffffffffffffffffffffff90818116606089015260801c604088015260a086013560c088015260c086013590811661010088015260801c610120870152612a8060e086018661284b565b801561357b576034811061351d578060141161019c578060241161019c5760341161019c57602481013560801c60a0880152601481013560801c60808801523560601c60e08701525b612ad285612480565b60208301526040860151946effffffffffffffffffffffffffffff8660c08901511760608901511760808901511760a0890151176101008901511761012089015117116134bf57604087015160608801510160808801510160a08801510160c0880151016101008801510296835173ffffffffffffffffffffffffffffffffffffffff81511690612b66604085018561284b565b806131e4575b505060e0015173ffffffffffffffffffffffffffffffffffffffff1690600082156131ac575b6020612bd7918b828a01516000868a604051978896879586937f19822f7c00000000000000000000000000000000000000000000000000000000855260048501613db5565b0393f160009181613178575b50612c8b573d8c610800808311612c83575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612bf5565b9a92939495969798999a91156130f2575b509773ffffffffffffffffffffffffffffffffffffffff835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492612cee84612416565b9055160361308d575a8503116130285773ffffffffffffffffffffffffffffffffffffffff60e0606093015116612d42575b509060a09184959697986040608096015260608601520135905a900301910152565b969550505a9683519773ffffffffffffffffffffffffffffffffffffffff60e08a01511680600052600060205260406000208054848110612fc3576080612dcd9a9b9c600093878094039055015192602089015183604051809d819582947f52b7512c0000000000000000000000000000000000000000000000000000000084528c60048501613db5565b039286f1978860009160009a612f36575b50612e86573d8b610800808311612e7e575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612df0565b9991929394959697989998925a900311612eab57509096959094939291906080612d20565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b915098503d90816000823e612f4b82826121ed565b604081838101031261019c5780519067ffffffffffffffff821161019c57828101601f83830101121561019c578181015191612f868361222e565b93612f9460405195866121ed565b838552820160208483850101011161019c57602092612fba9184808701918501016123a3565b01519838612dde565b60848b604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808c11613113578b9003905538612c9c565b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b9091506020813d6020116131a4575b81613194602093836121ed565b8101031261019c57519038612be3565b3d9150613187565b508060005260006020526040600020548a81116000146131d75750612bd7602060005b915050612b92565b6020612bd7918c036131cf565b833b61345a57604088510151602060405180927f570e1a360000000000000000000000000000000000000000000000000000000082528260048301528160008161323260248201898b612709565b039273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c1690f1908115610db75760009161343b575b5073ffffffffffffffffffffffffffffffffffffffff811680156133d6578503613371573b1561330c5760141161019c5773ffffffffffffffffffffffffffffffffffffffff9183887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391612b6c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b60848e604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b60848f604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b613454915060203d602011610db057610da181836121ed565b3861327c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b5050600060e087015260006080870152600060a0870152612ac9565b9092915a906060810151916040928351967fffffffff00000000000000000000000000000000000000000000000000000000886135d7606084018461284b565b600060038211613b9f575b7f8dd7712f0000000000000000000000000000000000000000000000000000000094168403613a445750505061379d6000926136b292602088015161363a8a5193849360208501528b602485015260648401906128ec565b90604483015203906136727fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0928381018352826121ed565b61379189519485927e42dc5300000000000000000000000000000000000000000000000000000000602085015261020060248501526102248401906123c6565b613760604484018b60806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152876123c6565b039081018352826121ed565b6020918183809351910182305af1600051988652156137bf575b505050505050565b909192939495965060003d8214613a3a575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361385b57608487878051917f220266b600000000000000000000000000000000000000000000000000000000835260048301526024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b7fdeadaa510000000000000000000000000000000000000000000000000000000091929395949650146000146138c55750506138a961389e6138b8935a90612443565b608085015190612409565b9083015183611d748295613d65565b905b3880808080806137b7565b909261395290828601518651907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479273ffffffffffffffffffffffffffffffffffffffff9580878551169401516139483d610800808211613a32575b508a519084818301018c5280825260008583013e8a805194859485528401528a8301906123c6565b0390a35a90612443565b916139636080860193845190612409565b926000905a94829488519761397789613ccc565b948260e08b0151168015600014613a1857505050875116955b5a9003019560a06060820151910151019051860390818111613a04575b5050840290850151928184106000146139de57505080611e68575090816139d89293611d7481613d65565b906138ba565b6139ee9082849397950390613c98565b50611e68575090826139ff92613cf6565b6139d8565b6064919003600a02049094019338806139ad565b90919892509751613a2a575b50613990565b955038613a24565b905038613920565b8181803e516137d1565b613b97945082935090613a8c917e42dc53000000000000000000000000000000000000000000000000000000006020613b6b9501526102006024860152610224850191612709565b613b3a604484018860806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152846123c6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018952886121ed565b60008761379d565b5081356135e2565b73ffffffffffffffffffffffffffffffffffffffff168015613c3a57600080809381935af1613bd4612450565b5015613bdc57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff166000526000602052613cc66040600020918254612409565b80915590565b610120610100820151910151808214613cf257480180821015613ced575090565b905090565b5090565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff946020868851169660e089015116970151916040519283526000602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b613dcd604092959493956060835260608301906128ec565b9460208201520152565b8015613e6457600060408051613dec816121d1565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff811690604065ffffffffffff91828160a01c16908115613e5c575b60d01c92825191613e37836121d1565b8583528460208401521691829101524211908115613e5457509091565b905042109091565b839150613e27565b5060009060009056fea2646970667358221220b094fd69f04977ae9458e5ba422d01cd2d20dbcfca0992ff37f19aa07deec25464736f6c63430008170033" ); + vm.etch( + _ERC4337_ENTRYPOINT_V08_ADDR, + hex"6101606040526004361015610024575b3615610019575f80fd5b610022336131f4565b005b5f610140525f3560e01c806242dc53146125d957806301ffc9a7146124875780630396cb60146120cc57806309ccb8801461205b5780630bd28e3b14611fbf57806313c65a6e14611f84578063154e58dc14611f295780631b2e01b814611e93578063205c287814611cf257806322cdde4c14611c6e57806335567e1a14611bb45780635287ce1214611a9457806370a0823114611a29578063765e827f1461198b57806384b0196e1461184b578063850aaf62146117865780639b249f6914611622578063b760faf9146115e1578063bb9fe6bf146113f2578063c23a5cea1461114f5763dbed18e00361000f5734610ec95761012136612d56565b6101005260e052610130613824565b6101405190815b60e0518110610f2e575061014a8261303a565b61012052610140516080526101405160c0525b60e05160c0511061029b577fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9726101405161014051a161014051608081905290815b60e05181106101e1576101b48361010051614a19565b610140517f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d6101405180f35b6102436101f18260e05185613267565b73ffffffffffffffffffffffffffffffffffffffff610212602083016132fb565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d6101405161014051a2806132a7565b9061014051915b80831061025c5750505060010161019e565b909194600190610289610270888587613109565b61027f60805161012051613176565b519060805161437c565b0195816080510160805201919061024a565b6102aa60c05160e05183613267565b73ffffffffffffffffffffffffffffffffffffffff6102d860206102ce84806132a7565b60a05293016132fb565b61014051911691905b60a05181106103055750505060a05160805101608052600160c0510160c05261015d565b610316816080510161012051613176565b516103248260a05185613109565b61014051915a81519273ffffffffffffffffffffffffffffffffffffffff61034b826132fb565b168452602081810135908501526fffffffffffffffffffffffffffffffff6080808301358281166060880152811c604087015260a083013560c0808801919091528301359182166101008701521c6101208501526103ac60e082018261331c565b9081610e15575b5050604051936103c282612ee9565b6020850152846040526040810151946effffffffffffffffffffffffffffff8660c08401511760608401511760808401511760a084015117610100840151176101208401511711610daf5750604081015160608201510160808201510160a08201510160c0820151016101008201510294856040860152845173ffffffffffffffffffffffffffffffffffffffff60e08183511692610475898d61046960408b018b61331c565b92909160805101614fb5565b0151169661014051978015610d7e575b87516040810151905173ffffffffffffffffffffffffffffffffffffffff169061014051506040519a8b8960208d01519260208301937f19822f7c00000000000000000000000000000000000000000000000000000000855260248401926104ec93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018d5261051c908d612c2d565b61014051908c5190846101405190602095f161014051519a3d602003610d73575b60405215610c80575015610c02575b505073ffffffffffffffffffffffffffffffffffffffff825116602083015190610140515260016020526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f20918254926105ba84612e80565b90551603610b99575a840311610b305760e0015160609073ffffffffffffffffffffffffffffffffffffffff16610827575b73ffffffffffffffffffffffffffffffffffffffff949260a0859360809360606106219801520135905a900301910152614f15565b911685036107be576107555761064b73ffffffffffffffffffffffffffffffffffffffff91614f15565b91166106ec5761065d576001016102e1565b60a490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9897969594505a9883519961085b73ffffffffffffffffffffffffffffffffffffffff60e08d015116604087015190615482565b15610ac75760807f52b7512c000000000000000000000000000000000000000000000000000000009798999a9b01516040516108dc816108b060208a015160408b015190602084019d8e528960248501615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b8651608073ffffffffffffffffffffffffffffffffffffffff60e08301511691015161014051918b61014051928551926101405191f1983d908161014051843e51948251604084019b8c519015918215610abb575b508115610a8b575b50610a065750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a90031161097a5750946105ec565b80887f220266b60000000000000000000000000000000000000000000000000000000060a4935260805101600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87610a1261349e565b6040519384937f65c8fd4d0000000000000000000000000000000000000000000000000000000085526080510160048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b0390fd5b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f610939565b6040141591505f610931565b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608487604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b610c0b91615482565b15610c17578b8061054c565b608488604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8b903b610cf057608490604051907f220266b600000000000000000000000000000000000000000000000000000000825260805101600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b610cf861349e565b90610a876040519283927f65c8fd4d00000000000000000000000000000000000000000000000000000000845260805101600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b61014051915061053d565b6101408051849052516020819052604090205490985081811115610da85750610140515b97610485565b8103610da2565b80887f220266b6000000000000000000000000000000000000000000000000000000006084935260805101600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411610ec95780359160248110610ec957603411610ec9576024810135608090811c60a0880152601490910135811c90860152606081901c15610e6b5760601c60e085015289806103b3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4141393820696e76616c6964207061796d6173746572000000000000000000006044820152fd5b6101405180fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b610f3b8160e05184613267565b92610f4684806132a7565b919073ffffffffffffffffffffffffffffffffffffffff610f69602088016132fb565b16956001871461111d5786610f86575b5050019250600101610137565b806040610f9492019061331c565b91873b15610ec957916040519283917f2dd8113300000000000000000000000000000000000000000000000000000000835286604484016040600486015252606483019160648860051b8501019281610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee182360301915b8b82106110c357505050505081611054917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8580950301602485015261014051956131b6565b0381610140518a5af190816110a8575b5061109b57847f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b929350839260015f610f79565b610140516110b591612c2d565b61014051610ec9575f611064565b9193967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c90879294969703018552863584811215610ec957602061110c600193858394016133bd565b98019501920188969594939161100e565b867f86a9f750000000000000000000000000000000000000000000000000000000006101405152600452602461014051fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611186612cde565b3361014051526101405160205260016040610140512001908154916dffffffffffffffffffffffffffff8360081c169283156113945760981c65ffffffffffff1680156113365742106112d85780547fffffffffffffff000000000000000000000000000000000000000000000000ff1690556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af161126d612eba565b501561127a576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9573361014051526101405160205260016040610140512001805463ffffffff8160781c169081156115835760ff16156115255765ffffffffffff4216019065ffffffffffff82116114f25780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609884901b1617905560405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a26101405180f35b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526011600452602461014051fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95761161b611616612cde565b6131f4565b6101405180f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec95760206116766116b1923690600401612d01565b60405193849283927f570e1a3600000000000000000000000000000000000000000000000000000000845285600485015260248401916131b6565b03816101405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000449ed7c3e6fee6a97311d4b55475df59c44add33165af180156117785773ffffffffffffffffffffffffffffffffffffffff916101405191611749575b507f6ca7b80600000000000000000000000000000000000000000000000000000000610140515216600452602461014051fd5b61176b915060203d602011611771575b6117638183612c2d565b81019061318a565b82611716565b503d611759565b6040513d61014051823e3d90fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576117bd612cde565b60243567ffffffffffffffff8111610ec9576117dd903690600401612d01565b604051929181908437820190610140518252610140519280610140519303915af4611806612eba565b90610a876040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190612de9565b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576119296118a87f4552433433333700000000000000000000000000000000000000000000000007614ccf565b6118d17f3100000000000000000000000000000000000000000000000000000000000001614e45565b60405190602090611937906118e68385612c2d565b6101405184525f3681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612de9565b908582036040870152612de9565b4660608501523060808501526101405160a085015283810360c0850152818084519283815201930191610140515b82811061197457505050500390f35b835185528695509381019392810192600101611965565b34610ec95761199936612d56565b6119a4929192613824565b6119ad8361303a565b6119b8818585613898565b5061014051927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a161014051915b8583106119f9576101b48585614a19565b909193600190611a1f611a0d878987613109565b611a178886613176565b51908861437c565b01940191906119e8565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611a75612cde565b1661014051526101405160205260206040610140512054604051908152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95773ffffffffffffffffffffffffffffffffffffffff611ae0612cde565b604051611aec81612bab565b6101405181526101405160208201526101405160408201526101405160608201526080610140519101521661014051526101405160205260a06040610140512065ffffffffffff604051611b3f81612bab565b63ffffffff60018454948584520154916dffffffffffffffffffffffffffff6020820160ff8516151581526040830190828660081c1682528660806060860195878960781c168752019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611bed612cde565b73ffffffffffffffffffffffffffffffffffffffff611c0a612d2f565b91166101405152600182526040610140512077ffffffffffffffffffffffffffffffffffffffffffffffff82165f52825260405f20547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043567ffffffffffffffff8111610ec9576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610ec957611cea602091600401612ee9565b604051908152f35b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611d29612cde565b6024359033610140515261014051602052604061014051208054808411611e355783611d5491612ead565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2610140519182918291829173ffffffffffffffffffffffffffffffffffffffff165af1611dca612eba565b5015611dd7576101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610ec95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957611eca612cde565b73ffffffffffffffffffffffffffffffffffffffff611ee7612d2f565b91166101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f52602052602060405f2054604051908152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760206040517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e8152f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576020611cea6134cb565b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610ec957336101405152600160205277ffffffffffffffffffffffffffffffffffffffffffffffff6040610140512091165f5260205260405f206120528154612e80565b90556101405180f35b34610ec957610140517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec957602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000449ed7c3e6fee6a97311d4b55475df59c44add33168152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec95760043563ffffffff8116809103610ec957336101405152610140516020526040610140512090801561242957600182015463ffffffff8160781c1682106123cb57612155906dffffffffffffffffffffffffffff349160081c16612e46565b91821561236d576dffffffffffffffffffffffffffff831161230f57546040516122d79161218282612bab565b815265ffffffffffff602082019160018352604081016dffffffffffffffffffffffffffff87168152606082019086825260016080840193610140518552336101405152610140516020526040610140512090518155019451151560ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008754169116178555517fffffffffffffffffffffffffffffffffff0000000000000000000000000000ff6effffffffffffffffffffffffffff008087549360081b16169116178455517fffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffff72ffffffff0000000000000000000000000000008086549360781b1616911617835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b60405191825260208201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a26101405180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610ec95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610ec9576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610ec957807f6930d3ee00000000000000000000000000000000000000000000000000000000602092149081156125af575b8115612585575b811561255b575b8115612531575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482612526565b7f3e84f021000000000000000000000000000000000000000000000000000000008114915061251f565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150612518565b7f989ccc580000000000000000000000000000000000000000000000000000000081149150612511565b34612a32576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112612a325760043567ffffffffffffffff8111612a325736602382011215612a325761263a903690602481600401359101612ca8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c08112612a32576101406040519161267683612bab565b12612a325760405161268781612bf4565b60243573ffffffffffffffffffffffffffffffffffffffff81168103612a3257815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff81168103612a325760e082015261012435610100820152610144356101208201528152602081019161016435835260408201906101843582526101a435606084015260808301916101c43583526101e43567ffffffffffffffff8111612a3257612760903690600401612d01565b955a90303303612b4d578651606081015195603f5a0260061c61271060a084015189010111612b25575f9681519182612a6b575b5050505050906127ac915a9003855101963691612ca8565b925a93855161010081015161012082015148018082105f14612a635750975b6127f873ffffffffffffffffffffffffffffffffffffffff60e08401511694518203606084015190614b09565b01925f928161290e5750505173ffffffffffffffffffffffffffffffffffffffff16945b5a900301019485029051928184105f146128ba5750506003811015612887576002036128595760209281611cea929361285481614c2a565b614b28565b7fdeadaa51000000000000000000000000000000000000000000000000000000006101405152602061014051fd5b7f4e487b710000000000000000000000000000000000000000000000000000000061014051526021600452602461014051fd5b816128f0929594969396039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b5060038410156128875782612909926020951590614ba9565b611cea565b909691878251612921575b50505061281c565b90919293505a926003881015612a365760028803612957575b505060a061294e925a900391015190614b09565b90888080612919565b60a083015191803b15612a32578b925f92836129b3938c8b88604051998a98899788957f7c627b210000000000000000000000000000000000000000000000000000000087526004870152608060248701526084860190612de9565b9202604484015260648301520393f19081612a1d575b50612a1357610a876129d961349e565b6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190612de9565b60a061294e61293a565b5f612a2791612c2d565b5f610140528a6129c9565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9050976127cb565b915f9291838093602073ffffffffffffffffffffffffffffffffffffffff885116910192f115612a9e575b808080612794565b6127ac9392955060405191612ab161349e565b908151612aca575b505050604052600193909188612a96565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201905191602073ffffffffffffffffffffffffffffffffffffffff855116940151612b1a60405192839283612e2c565b0390a3888080612ab9565b7fdeaddead000000000000000000000000000000000000000000000000000000005f5260205ffd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117612bc757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610140810190811067ffffffffffffffff821117612bc757604052565b6060810190811067ffffffffffffffff821117612bc757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612bc757604052565b67ffffffffffffffff8111612bc757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612cb482612c6e565b91612cc26040519384612c2d565b829481845281830111612a32578281602093845f960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9181601f84011215612a325782359167ffffffffffffffff8311612a325760208381860195010111612a3257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff82168203612a3257565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112612a325760043567ffffffffffffffff8111612a325760040182601f82011215612a325780359267ffffffffffffffff8411612a32576020808301928560051b010111612a3257919060243573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b604090612e43939281528160208201520190612de9565b90565b91908201809211612e5357565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612e535760010190565b91908203918211612e5357565b3d15612ee4573d90612ecb82612c6e565b91612ed96040519384612c2d565b82523d5f602084013e565b606090565b604290612ef5816135f4565b612efd6134cb565b91612f07816132fb565b91801561300557905b60c0612f1f606083018361331c565b90816040519182372091612f3660e082018261331c565b908160405191823720926040519473ffffffffffffffffffffffffffffffffffffffff60208701977f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e895216604087015260208301356060870152608086015260a085015260808101358285015260a081013560e085015201356101008301526101208201526101208152612fcd61014082612c2d565b519020604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b50613013604082018261331c565b90816040519182372090612f10565b67ffffffffffffffff8111612bc75760051b60200190565b9061304482613022565b6130516040519182612c2d565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061307f8294613022565b01905f5b82811061308f57505050565b60209060405161309e81612bab565b6040516130aa81612bf4565b5f81525f848201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201525f61012082015281525f838201525f60408201525f60608201525f608082015282828501015201613083565b91908110156131495760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215612a32570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80518210156131495760209160051b010190565b90816020910312612a32575173ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61325b348573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b936040519485521692a2565b91908110156131495760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215612a32570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918160051b36038313612a3257565b3573ffffffffffffffffffffffffffffffffffffffff81168103612a325790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612a32570180359067ffffffffffffffff8211612a3257602001918136038313612a3257565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612a3257016020813591019167ffffffffffffffff8211612a32578136038313612a3257565b80359173ffffffffffffffffffffffffffffffffffffffff83168303612a325773ffffffffffffffffffffffffffffffffffffffff612e43931681526020820135602082015261348f61348361344a61342f61341c604087018761336d565b61012060408801526101208701916131b6565b61343c606087018761336d565b9086830360608801526131b6565b6080850135608085015260a085013560a085015260c085013560c085015261347560e086018661336d565b9085830360e08701526131b6565b9261010081019061336d565b916101008185039101526131b6565b3d61080081116134c2575b604051906020818301016040528082525f602083013e90565b506108006134a9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108163014806135cb575b15613533577f1cb06c861549b538545a86964847e07ba0bcd7699008fe569947aabf7d4dc16a90565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f364da28a5c92bcc87fe97c8813a6c6b8a3a049b0ea0a328fcb0b4f0e0033758660408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526135c560c082612c2d565b51902090565b507f0000000000000000000000000000000000000000000000000000000000000001461461350a565b613601604082018261331c565b909161360d8284614c7a565b1561381d5761361b906132fb565b60175f80833c5f51907fef010000000000000000000000000000000000000000000000000000000000007fffffff000000000000000000000000000000000000000000000000000000000083160361375b575060181b91601482116136bb5750506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808060208401941616168252601481526135c5603482612c2d565b81601411612a325760206135c5916040519384917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808086860199161616875260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec83019101603484013781015f8382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b3b156137bf5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f73656e64657220686173206e6f20636f646500000000000000000000000000006044820152fd5b5050505f90565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6138705760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b92919092835f5b8181106138ac5750505050565b6138b68185613176565b516138c2828486613109565b5f915a81519273ffffffffffffffffffffffffffffffffffffffff6138e6826132fb565b168452602081013560208501526080810135936fffffffffffffffffffffffffffffffff8560801c951694604082019060608301968752815260c0820160a0840135815260c0840135906fffffffffffffffffffffffffffffffff8260801c9216916101208501906101008601938452815261396560e087018761331c565b9081614316575b505060405161397a87612ee9565b9960208a019a8b528160405285519586855117825117926effffffffffffffffffffffffffffff60808a01948551179560a08b0196875117895117905117116142b45750519051019051019051019051019051029560408601918783528973ffffffffffffffffffffffffffffffffffffffff60e08951613a0f8b8483511695613a0760408d018d61331c565b929091614fb5565b015116985f99801561428d575b89516040810151905173ffffffffffffffffffffffffffffffffffffffff1680916040519d8e808d8b519360208301947f19822f7c0000000000000000000000000000000000000000000000000000000086526024840192613a7d93615460565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018252613aad9082612c2d565b51905f6020948194f15f519c3d602003614285575b6040521561419a575015614120575b505073ffffffffffffffffffffffffffffffffffffffff8451166020850151905f52600160205260405f2077ffffffffffffffffffffffffffffffffffffffffffffffff8260401c165f5260205267ffffffffffffffff60405f2091825492613b3984612e80565b905516036140bb575a8603116140565773ffffffffffffffffffffffffffffffffffffffff60e0606094015116613d96575b505073ffffffffffffffffffffffffffffffffffffffff949260a085936080936060613ba29801520135905a900301910152614f15565b9116613d3157613ccc57613bca73ffffffffffffffffffffffffffffffffffffffff91614f15565b9116613c6757613bdc5760010161389f565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b909c9b9a99989796505a9085519d60e08f015173ffffffffffffffffffffffffffffffffffffffff168151613dca91615482565b15613ff157613e1d7f52b7512c00000000000000000000000000000000000000000000000000000000999a9b9c9d9e9f60800151926108b060405193849251905190602084019d8e528960248501615460565b5f8088518b82608073ffffffffffffffffffffffffffffffffffffffff60e08501511693015192865193f1983d90815f843e51948251604084019b8c519015918215613fe5575b508115613fb5575b50613f385750601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101160191826040525a900311613eb05750948260a0613b6b565b80887f220266b60000000000000000000000000000000000000000000000000000000060a49352600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b8b610a87613f4461349e565b6040519384937f65c8fd4d00000000000000000000000000000000000000000000000000000000855260048501526024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b9050601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084019101105f613e6c565b6040141591505f613e64565b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b61412991615482565b15614135575f80613ad1565b60848a604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b8d903b61420657608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601960448201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006064820152fd5b61420e61349e565b90610a876040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190612de9565b5f9150613ac2565b9950815f525f60205260405f20548181115f146142ad57505f5b99613a1c565b81036142a7565b808f7f220266b60000000000000000000000000000000000000000000000000000000060849352600482015260406024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152fd5b60348210610ed05781601411612a3257803560601c9160248110612a3257601482013590603411612a32576fffffffffffffffffffffffffffffffff60248193013560801c1660a089015260801c1660808701528015610e6b5760e08601525f8061396c565b9092915a60608201516040519586614397606083018361331c565b5f60038211614a11575b7fffffffff00000000000000000000000000000000000000000000000000000000167f8dd7712f00000000000000000000000000000000000000000000000000000000036148a3575050505f6144ae6145a261443c61446e602095868a01516040519384927f8dd7712f000000000000000000000000000000000000000000000000000000008a8501526040602485015260648401906133bd565b906044830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c2d565b6108b06040519384927e42dc5300000000000000000000000000000000000000000000000000000000888501526102006024850152610224840190612de9565b614571604484018b60806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287612de9565b828151910182305af15f5196604052156145bd575b50505050565b9091929394505f3d602014614896575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361465957608485604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b92935090917fdeadaa5100000000000000000000000000000000000000000000000000000000036146bc57506146a16146966146b1925a90612ead565b608084015190612e46565b6040830151836128548295614c2a565b905b5f8080806145b7565b9061472f9060405160208501518551907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f4792602073ffffffffffffffffffffffffffffffffffffffff84511693015161471261349e565b9061472260405192839283612e2c565b0390a36040525a90612ead565b61473f6080840191825190612e46565b915f905a92855161010081015161012082015148018082105f1461488e5750955b61478d73ffffffffffffffffffffffffffffffffffffffff60e08401511693518203606084015190614b09565b01925f928061485f5750505173ffffffffffffffffffffffffffffffffffffffff16935b5a900301019283026040850151928184105f14614813575050806147e6575090816147e0929361285481614c2a565b906146b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b614848908284939795039073ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f209081540180915590565b506147e6575090825f61485a93614ba9565b6147e0565b9591905161486e575b506147b1565b935090506148875a9360a05f955a900391015190614b09565b905f614868565b905095614760565b5060205f803e5f516145cd565b614a0893506149dc916148e8917e42dc5300000000000000000000000000000000000000000000000000000000602086015261020060248601526102248501916131b6565b6149ab604484018860806101a091610120815173ffffffffffffffffffffffffffffffffffffffff8151168652602081015160208701526040810151604087015260608101516060870152838101518487015260a081015160a087015260c081015160c087015273ffffffffffffffffffffffffffffffffffffffff60e08201511660e087015261010081015161010087015201516101208501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284612de9565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101885287612c2d565b60205f876145a2565b5081356143a1565b73ffffffffffffffffffffffffffffffffffffffff168015614aab575f80809381935af1614a45612eba565b5015614a4d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b90619c408201811115614b2257606491600a9103020490565b50505f90565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff86511694602073ffffffffffffffffffffffffffffffffffffffff60e089015116970151916040519283525f602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519573ffffffffffffffffffffffffffffffffffffffff87511695602073ffffffffffffffffffffffffffffffffffffffff60e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b90600211614cca57357fffffffffffffffffffffffffffffffffffffffff000000000000000000000000167f77020000000000000000000000000000000000000000000000000000000000001490565b505f90565b60ff8114614d2e5760ff811690601f8211614d065760405191614cf3604084612c2d565b6020808452838101919036833783525290565b7fb3512b0c000000000000000000000000000000000000000000000000000000005f5260045ffd5b506040515f6002548060011c9160018216918215614e3b575b602084108314614e0e578385528492908115614dd15750600114614d72575b612e4392500382612c2d565b5060025f90815290917f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b818310614db5575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614d9d565b60209250612e439491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101614d66565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b92607f1692614d47565b60ff8114614e695760ff811690601f8211614d065760405191614cf3604084612c2d565b506040515f6003548060011c9160018216918215614f0b575b602084108314614e0e578385528492908115614dd15750600114614eac57612e4392500382612c2d565b5060035f90815290917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b818310614eef575050906020612e4392820101614d66565b6020919350806001915483858801015201910190918392614ed7565b92607f1692614e82565b8015614fae575f60408051614f2981612c11565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff81169065ffffffffffff8160a01c16908115614fa0575b60409060d01c9165ffffffffffff825191614f7a83612c11565b8583528460208401521691829101524211908115614f9757509091565b90504211159091565b65ffffffffffff9150614f60565b505f905f90565b929190915f9080614fc8575b5050505050565b83519473ffffffffffffffffffffffffffffffffffffffff86511695614fee8386614c7a565b61535f5750853b6152fa576014821061529557604085510151602060405180927f570e1a36000000000000000000000000000000000000000000000000000000008252826004830152818781615048602482018a8d6131b6565b039273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000449ed7c3e6fee6a97311d4b55475df59c44add331690f190811561528a57849161526b575b5073ffffffffffffffffffffffffffffffffffffffff811680156152065787036151a1573b1561513c5750601411615139577fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d91604091503573ffffffffffffffffffffffffffffffffffffffff60e06020860151955101511673ffffffffffffffffffffffffffffffffffffffff83519260601c1682526020820152a35f80808080614fc1565b80fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b615284915060203d602011611771576117638183612c2d565b5f615091565b6040513d86823e3d90fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f4141393920696e6974436f646520746f6f20736d616c6c0000000000000000006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b945050919050601482116153735750505050565b604073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000449ed7c3e6fee6a97311d4b55475df59c44add33169301519082601411612a3257833b15612a32575f809461542f96604051978896879586937fc09ad0d900000000000000000000000000000000000000000000000000000000855260048501526040602485015260147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec60448601930191016131b6565b0393f1801561545557615445575b8080806145b7565b5f61544f91612c2d565b5f61543d565b6040513d5f823e3d90fd5b615478604092959493956060835260608301906133bd565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090815481811061381d5703905560019056fea2646970667358221220a2ee7c02d47f72772240d0dfa7174d99b6049a68ccdf3d4434c3918f6bd9c1e164736f6c634300081c0033" + ); vm.etch( _ZERODEV_KERNEL_FACTORY_ADDR, hex"6080806040526004361015610012575f80fd5b5f3560e01c90816348aac39214610250575080635c60da1b146102085763ea6d13ac1461003d575f80fd5b6100463661033f565b60405161006c602080838181019587898837878201908382015203018084520182610394565b519020905f92604051927fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f36060527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e20766040526160096020527f000000000000000000000000d6cedde84be40893d153be9d467cd6ad37875b28601e5268603d3d8160223d3973600a52605f60212060358501523060581b845260ff84538060158501526055842094341591863b156101eb5750506001906101e6575f38818034895af1156101d9575b836040525f60605215610157575b6040516001600160a01b0385168152602090f35b9180825f9493859483378101838152039082855af13d156101d4573d67ffffffffffffffff81116101c0576040519061019a601f8201601f191660200183610394565b81525f60203d92013e5b156101b1575f8080610143565b63487e630960e11b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b6101a4565b63b12d13eb5f526004601cfd5b610135565b91509450605f602134f593846101355763301164255f526004601cfd5b3461024c575f36600319011261024c576040517f000000000000000000000000d6cedde84be40893d153be9d467cd6ad37875b286001600160a01b03168152602090f35b5f80fd5b3461024c57806102826020806102653661033f565b908084889499019889378201908382015203018084520182610394565b5190206040517fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f36060527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e20766040526160096020527f000000000000000000000000d6cedde84be40893d153be9d467cd6ad37875b28601e5268603d3d8160223d3973600a52605f602120906040525f60605260ff5f536035523060601b600152601552602060555f205f6035526040519060018060a01b03168152f35b90604060031983011261024c5760043567ffffffffffffffff811161024c578260238201121561024c5780600401359267ffffffffffffffff841161024c576024848301011161024c57602401919060243590565b90601f8019910116810190811067ffffffffffffffff8211176101c05760405256" @@ -193,6 +210,10 @@ contract BenchmarkTest is BaseTest { _PIMLICO_PAYMASTER_V07, hex"6080604052600436106101965760003560e01c80637c627b21116100e1578063c23a5cea1161008a578063d547741f11610064578063d547741f146104aa578063eb12d61e146104ca578063ec87621c146104ea578063feaf513e1461051e57600080fd5b8063c23a5cea1461046d578063c399ec881461048d578063d0e30db0146104a257600080fd5b8063a217fddf116100bb578063a217fddf14610402578063b0d691fe14610417578063bb9fe6bf1461045857600080fd5b80637c627b21146103715780637dd345cb1461039157806391d14854146103b157600080fd5b806336568abe116101435780635525dcfb1161011d5780635525dcfb1461030157806363b241aa14610321578063736c0d5b1461034157600080fd5b806336568abe146102835780634031c20e146102a357806352b7512c146102d357600080fd5b8063205c287811610174578063205c287814610206578063248a9ca3146102265780632f2ff15d1461026357600080fd5b806301ffc9a71461019b5780630396cb60146101d15780630e316ab7146101e6575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004612c22565b61053e565b6040516101c89190612c55565b60405180910390f35b6101e46101df366004612c7a565b6105d7565b005b3480156101f257600080fd5b506101e4610201366004612ccd565b610752565b34801561021257600080fd5b506101e4610221366004612cff565b6108a1565b34801561023257600080fd5b50610256610241366004612d3c565b60009081526020819052604090206001015490565b6040516101c89190612d63565b34801561026f57600080fd5b506101e461027e366004612d71565b610957565b34801561028f57600080fd5b506101e461029e366004612d71565b610982565b3480156102af57600080fd5b506101bb6102be366004612ccd565b60026020526000908152604090205460ff1681565b3480156102df57600080fd5b506102f36102ee366004612dc0565b6109e0565b6040516101c8929190612e9e565b34801561030d57600080fd5b5061025661031c366004612ebe565b610a03565b34801561032d57600080fd5b5061025661033c366004612f36565b610a40565b34801561034d57600080fd5b506101bb61035c366004612ccd565b60016020526000908152604090205460ff1681565b34801561037d57600080fd5b506101e461038c366004612fee565b610bf7565b34801561039d57600080fd5b506101e46103ac3660046130d0565b610c13565b3480156103bd57600080fd5b506101bb6103cc366004612d71565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561040e57600080fd5b50610256600081565b34801561042357600080fd5b5061044b7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da03281565b6040516101c8919061317d565b34801561046457600080fd5b506101e4610dcd565b34801561047957600080fd5b506101e4610488366004612ccd565b610f12565b34801561049957600080fd5b50610256610fa9565b6101e4611064565b3480156104b657600080fd5b506101e46104c5366004612d71565b611105565b3480156104d657600080fd5b506101e46104e5366004612ccd565b61112a565b3480156104f657600080fd5b506102567f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b34801561052a57600080fd5b506102566105393660046131ae565b611273565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806105d157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1615801561064557503360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b156106a957337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016106a0929190613222565b60405180910390fd5b6040517f0396cb6000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da0321690630396cb6090349061071d908590600401613249565b6000604051808303818588803b15801561073657600080fd5b505af115801561074a573d6000803e3d6000fd5b505050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff161580156107c057503360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b1561081b57337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016106a0929190613222565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600160205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b90610896908390613257565b60405180910390a150565b60006108ac816112fb565b6040517f205c287800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032169063205c2878906109209086908690600401613222565b600060405180830381600087803b15801561093a57600080fd5b505af115801561094e573d6000803e3d6000fd5b50505050505050565b600082815260208190526040902060010154610972816112fb565b61097c8383611308565b50505050565b73ffffffffffffffffffffffffffffffffffffffff811633146109d1576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109db8282611404565b505050565b606060006109ec6114bf565b6109f7858585611530565b91509150935093915050565b6000670de0b6b3a764000082610a198587613294565b610a2390886132b3565b610a2d9190613294565b610a3791906132f5565b95945050505050565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168360ff1603610acc57610ac582610abd7f000000000000000000000000000000000000000000000000000000000000000c7f0000000000000000000000000000000000000000000000000000000000000001613309565b60ff166116f4565b90506105d1565b6000610b187f00000000000000000000000000000000000000000000000000000000000000757f0000000000000000000000000000000000000000000000000000000000000001613309565b90506000610b2960e0850185613326565b610b7660ff7f0000000000000000000000000000000000000000000000000000000000000001167f00000000000000000000000000000000000000000000000000000000000000346132b3565b818110610b8557610b856133a3565b919091013560f81c9150506001811615156002821615156004831615801590610bb657610bb3601086613309565b94505b8215610bca57610bc7601086613309565b94505b8115610bde57610bdb601486613309565b94505b610beb878660ff166116f4565b98975050505050505050565b610bff6114bf565b610c0c8585858585611810565b5050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16158015610c8157503360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b15610cdc57337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016106a0929190613222565b60005b8281101561097c578160026000868685818110610cfe57610cfe6133a3565b9050602002016020810190610d139190612ccd565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790557f8ff8c5211f68ef53b4bdd15ab2ea6d87be8a3dbf58865bd8325c984057e4fcb4848483818110610d9957610d996133a3565b9050602002016020810190610dae9190612ccd565b83604051610dbd9291906133d2565b60405180910390a1600101610cdf565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16158015610e3b57503360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b15610e9657337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016106a0929190613222565b7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da03273ffffffffffffffffffffffffffffffffffffffff1663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610efe57600080fd5b505af115801561097c573d6000803e3d6000fd5b6000610f1d816112fb565b6040517fc23a5cea00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032169063c23a5cea90610f8f908590600401613257565b600060405180830381600087803b15801561073657600080fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da03216906370a082319061101e903090600401613257565b602060405180830381865afa15801561103b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105f91906133f8565b905090565b6040517fb760faf900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032169063b760faf99034906110d8903090600401613257565b6000604051808303818588803b1580156110f157600080fd5b505af1158015610c0c573d6000803e3d6000fd5b600082815260208190526040902060010154611120816112fb565b61097c8383611404565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1615801561119857503360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b156111f357337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016106a0929190613222565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055517f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f2490610896908390613257565b600080806fffffffffffffffffffffffffffffffff8616611294888a6132f5565b61129e91906132b3565b9050848111156112b5576112b28582613419565b91505b6000828511156112e4576064600a6112cd8588613419565b6112d79190613294565b6112e191906132f5565b90505b6112ee8882613294565b9998505050505050505050565b6113058133611a1c565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff166113fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561139a3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016105d1565b5060006105d1565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16156113fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016105d1565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032161461152e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a09061342c565b565b606060008080368161156e61154860e08b018b613326565b7f0000000000000000000000000000000000000000000000000000000000000034611a8b565b93509350935093508215801561159457503260009081526002602052604090205460ff16155b156115cd57326040517f55d3ab460000000000000000000000000000000000000000000000000000000081526004016106a09190613257565b7f000000000000000000000000000000000000000000000000000000000000000160ff168460ff161415801561162957507f000000000000000000000000000000000000000000000000000000000000000060ff168460ff1614155b15611660576040517f654a4f2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606060007f000000000000000000000000000000000000000000000000000000000000000060ff168660ff16036116a35761169d8b85858d611b38565b90925090505b7f000000000000000000000000000000000000000000000000000000000000000160ff168660ff16036116e4576116de868c86868e8e611cd1565b90925090505b909a909950975050505050505050565b60008083356020850135608086013560a087013560c088013561171a60408a018a613326565b604051611728929190613486565b60405190819003902061173e60608b018b613326565b60405161174c929190613486565b60405190819003902061176260e08c018c613326565b60009061178f8d7f00000000000000000000000000000000000000000000000000000000000000346132b3565b9261179c93929190613493565b6040516117aa929190613486565b6040519081900381206117c698979695949392916020016134c3565b60405160208183030381529060405280519060200120905080466040516020016117f192919061352d565b6040516020818303038152906040528051906020012091505092915050565b600061181c8585611e0a565b9050600061183b84848460800151856101600151866101400151611273565b9050600061184982866132b3565b905060008361018001516fffffffffffffffffffffffffffffffff1661188b8386608001516fffffffffffffffffffffffffffffffff16888860600151610a03565b61189591906132b3565b9050600084610120015182116118bb57818561012001516118b69190613419565b6118cb565b6101208501516118cb9083613419565b905061190d856020015186610120015184116118eb5786604001516118ee565b86515b8761012001518511611901578751611907565b87604001515b84611e8e565b6000670de0b6b3a7640000866060015187610100015161192d9190613294565b61193791906132f5565b6101a087015190915073ffffffffffffffffffffffffffffffffffffffff161580159061196357508281115b1561198a57602086015186516101a088015161198a9291906119858786613419565b611e8e565b856000015173ffffffffffffffffffffffffffffffffffffffff168660a001517f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd27f00000000000000000000000000000000000000000000000000000000000000018960200151878b60600151604051611a079493929190613544565b60405180910390a35050505050505050505050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16611a875780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016106a0929190613222565b5050565b6000803681611a9b8560016132b3565b861015611ad4576040517fcc32193e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878787818110611ae857611ae86133a3565b919091013560f881901c925060018084161515925060f99190911c9036906000908c908c90611b18908d906132b3565b611b23928290613493565b939d949c509a50919850919650505050505050565b60606000806000366000611b4c8989611eeb565b93509350935093506000611bb6611b837f00000000000000000000000000000000000000000000000000000000000000008d610a40565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b90506000611bfa8285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ff692505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205491925060ff90911690611c3582158989612020565b90508d3573ffffffffffffffffffffffffffffffffffffffff168b7f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd27f00000000000000000000000000000000000000000000000000000000000000006000806000604051611ca7949392919061358e565b60405180910390a36040805160208101909152600081529e909d509b505050505050505050505050565b6060600080611ce08787612058565b90506000611cf1611b838b8b610a40565b90506000611d03828460c00151611ff6565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020908152604080832054918701519087015193945060ff90911692611d4991841591612020565b90506000611d598d8b888c6127bc565b905082611d6e5796509450611dff9350505050565b6000611d818a6000808a60a00151610a03565b9050808761010001511115611dc2576040517f79183c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010087015115611df557611df587608001518f6000016020810190611de89190612ccd565b89516101008b0151611e8e565b5096509450505050505b965096945050505050565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152611e87828401846137a1565b9392505050565b60405181606052826040528360601b602c526f23b872dd000000000000000000000000600c52602060006064601c6000895af13d156001600051141716611edd57637939f4246000526004601cfd5b600060605260405250505050565b600080368160ff7f000000000000000000000000000000000000000000000000000000000000000c16851015611f4d576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611f5c600682888a613493565b611f65916137c3565b60d01c90506000611f7a600c6006898b613493565b611f83916137c3565b60d01c9050366000611f9889600c818d613493565b909250905060408114801590611faf575060418114155b15611fe6576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9299919850965090945092505050565b600080600080612006868661294e565b925092509250612016828261299b565b5090949350505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561204857600061204b565b60015b60ff161717949350505050565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c082015260e081018290526101008101829052610120810182905261014081019190915260ff7f00000000000000000000000000000000000000000000000000000000000000751682101561210d576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008084848281612120576121206133a3565b919091013560f81c9150506001808216151590600283161515906004841615159061214b908661382e565b9450876fffffffffffffffffffffffffffffffff86168861216d88600661382e565b6fffffffffffffffffffffffffffffffff169261218c93929190613493565b612195916137c3565b60d01c60208701526121a860068661382e565b9450876fffffffffffffffffffffffffffffffff8616886121ca88600661382e565b6fffffffffffffffffffffffffffffffff16926121e993929190613493565b6121f2916137c3565b60d01c604087015261220560068661382e565b9450876fffffffffffffffffffffffffffffffff86168861222788601461382e565b6fffffffffffffffffffffffffffffffff169261224693929190613493565b61224f9161385a565b60601c608087015261226260148661382e565b9450876fffffffffffffffffffffffffffffffff86168861228488601061382e565b6fffffffffffffffffffffffffffffffff16926122a393929190613493565b6122ac916138b8565b60801c60608701526122bf60108661382e565b9450876fffffffffffffffffffffffffffffffff8616886122e188602061382e565b6fffffffffffffffffffffffffffffffff169261230093929190613493565b61230991613916565b60a087015261231960208661382e565b9450876fffffffffffffffffffffffffffffffff86168861233b88601061382e565b6fffffffffffffffffffffffffffffffff169261235a93929190613493565b612363916138b8565b60801c60e087015261237660108661382e565b9450876fffffffffffffffffffffffffffffffff86168861239888601461382e565b6fffffffffffffffffffffffffffffffff16926123b793929190613493565b6123c09161385a565b60601c86526123d060148661382e565b600061010088015294508015612495576123eb85601061382e565b6fffffffffffffffffffffffffffffffff16871015612436576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b876fffffffffffffffffffffffffffffffff86168861245688601061382e565b6fffffffffffffffffffffffffffffffff169261247593929190613493565b61247e916138b8565b60801c61010087015261249260108661382e565b94505b60006101208701528215612558576124ae85601061382e565b6fffffffffffffffffffffffffffffffff168710156124f9576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b876fffffffffffffffffffffffffffffffff86168861251988601061382e565b6fffffffffffffffffffffffffffffffff169261253893929190613493565b612541916138b8565b60801c61012087015261255560108661382e565b94505b6000610140870152811561261b5761257185601461382e565b6fffffffffffffffffffffffffffffffff168710156125bc576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b876fffffffffffffffffffffffffffffffff8616886125dc88601461382e565b6fffffffffffffffffffffffffffffffff16926125fb93929190613493565b6126049161385a565b60601c61014087015261261860148661382e565b94505b612639876fffffffffffffffffffffffffffffffff8716818b613493565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060c0870152608086015173ffffffffffffffffffffffffffffffffffffffff166126c3576040517f33c1dac900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560a00151600003612701576040517f5b33c69600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818015612727575061014086015173ffffffffffffffffffffffffffffffffffffffff16155b1561275e576040517f497189f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560c001515160401415801561277a57508560c0015151604114155b156127b1576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505092915050565b606060006127c986612a9d565b6127d287612acd565b6127dc91906132b3565b905060008460e001516fffffffffffffffffffffffffffffffff1661280088612aeb565b61280e9060a08a01356132b3565b61281891906132b3565b604080516101c081019091529091508061283560208a018a612ccd565b73ffffffffffffffffffffffffffffffffffffffff168152602001866080015173ffffffffffffffffffffffffffffffffffffffff168152602001866000015173ffffffffffffffffffffffffffffffffffffffff1681526020018660a00151815260200186606001516fffffffffffffffffffffffffffffffff168152602001878152602001600081526020016000815260200185815260200186610100015181526020018381526020018281526020018661012001516fffffffffffffffffffffffffffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff168152506040516020016129339190613a7f565b60405160208183030381529060405292505050949350505050565b600080600083516041036129885760208401516040850151606086015160001a61297a88828585612afb565b955095509550505050612994565b50508151600091506002905b9250925092565b60008260038111156129af576129af613a8e565b036129b8575050565b60018260038111156129cc576129cc613a8e565b03612a03576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115612a1757612a17613a8e565b03612a50576040517ffce698f70000000000000000000000000000000000000000000000000000000081526106a0908290600401612d63565b6003826003811115612a6457612a64613a8e565b03611a8757806040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004016106a09190612d63565b6000612aac60e0830183613326565b612abb91603491602491613493565b612ac4916138b8565b60801c92915050565b60006fffffffffffffffffffffffffffffffff6080830135166105d1565b60006105d1826080013560801c90565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612b365750600091506003905082612bde565b600060018888888860405160008152602001604052604051612b5b9493929190613abd565b6020604051602081039080840390855afa158015612b7d573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612bd457506000925060019150829050612bde565b9250600091508190505b9450945094915050565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b811461130557600080fd5b80356105d181612be8565b600060208284031215612c3757612c37600080fd5b6000612c438484612c17565b949350505050565b8015155b82525050565b602081016105d18284612c4b565b63ffffffff8116612c0c565b80356105d181612c63565b600060208284031215612c8f57612c8f600080fd5b6000612c438484612c6f565b600073ffffffffffffffffffffffffffffffffffffffff82166105d1565b612c0c81612c9b565b80356105d181612cb9565b600060208284031215612ce257612ce2600080fd5b6000612c438484612cc2565b80612c0c565b80356105d181612cee565b60008060408385031215612d1557612d15600080fd5b6000612d218585612cc2565b9250506020612d3285828601612cf4565b9150509250929050565b600060208284031215612d5157612d51600080fd5b6000612c438484612cf4565b80612c4f565b602081016105d18284612d5d565b60008060408385031215612d8757612d87600080fd5b6000612d938585612cf4565b9250506020612d3285828601612cc2565b60006101208284031215612dba57612dba600080fd5b50919050565b600080600060608486031215612dd857612dd8600080fd5b833567ffffffffffffffff811115612df257612df2600080fd5b612dfe86828701612da4565b9350506020612e0f86828701612cf4565b9250506040612e2086828701612cf4565b9150509250925092565b60005b83811015612e45578181015183820152602001612e2d565b50506000910152565b6000612e58825190565b808452602084019350612e6f818560208601612e2a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b60408082528101612eaf8185612e4e565b9050611e876020830184612d5d565b60008060008060808587031215612ed757612ed7600080fd5b6000612ee38787612cf4565b9450506020612ef487828801612cf4565b9350506040612f0587828801612cf4565b9250506060612f1687828801612cf4565b91505092959194509250565b60ff8116612c0c565b80356105d181612f22565b60008060408385031215612f4c57612f4c600080fd5b6000612f588585612f2b565b925050602083013567ffffffffffffffff811115612f7857612f78600080fd5b612d3285828601612da4565b6003811061130557600080fd5b80356105d181612f84565b60008083601f840112612fb157612fb1600080fd5b50813567ffffffffffffffff811115612fcc57612fcc600080fd5b602083019150836001820283011115612fe757612fe7600080fd5b9250929050565b60008060008060006080868803121561300957613009600080fd5b60006130158888612f91565b955050602086013567ffffffffffffffff81111561303557613035600080fd5b61304188828901612f9c565b9450945050604061305488828901612cf4565b925050606061306588828901612cf4565b9150509295509295909350565b60008083601f84011261308757613087600080fd5b50813567ffffffffffffffff8111156130a2576130a2600080fd5b602083019150836020820283011115612fe757612fe7600080fd5b801515612c0c565b80356105d1816130bd565b6000806000604084860312156130e8576130e8600080fd5b833567ffffffffffffffff81111561310257613102600080fd5b61310e86828701613072565b93509350506020612e20868287016130c5565b60006105d173ffffffffffffffffffffffffffffffffffffffff8316613145565b90565b73ffffffffffffffffffffffffffffffffffffffff1690565b60006105d182613121565b60006105d18261315e565b612c4f81613169565b602081016105d18284613174565b6fffffffffffffffffffffffffffffffff8116612c0c565b80356105d18161318b565b600080600080600060a086880312156131c9576131c9600080fd5b60006131d58888612cf4565b95505060206131e688828901612cf4565b94505060406131f7888289016131a3565b935050606061320888828901612cf4565b925050608061306588828901612cf4565b612c4f81612c9b565b604081016132308285613219565b611e876020830184612d5d565b63ffffffff8116612c4f565b602081016105d1828461323d565b602081016105d18284613219565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181028082158382048514176132ac576132ac613265565b5092915050565b808201808211156105d1576105d1613265565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613304576133046132c6565b500490565b60ff9182169190811690828201908111156105d1576105d1613265565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13685900301811261335f5761335f600080fd5b80840192508235915067ffffffffffffffff82111561338057613380600080fd5b60208301925060018202360383131561339b5761339b600080fd5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b604081016133e08285613219565b611e876020830184612c4b565b80516105d181612cee565b60006020828403121561340d5761340d600080fd5b6000612c4384846133ed565b818103818111156105d1576105d1613265565b602080825281016105d181601581527f53656e646572206e6f7420456e747279506f696e740000000000000000000000602082015260400190565b82818337506000910152565b6000613480838584613467565b50500190565b6000612c43828486613473565b600080858511156134a6576134a6600080fd5b838611156134b6576134b6600080fd5b5050820193919092039150565b61010081016134d2828b613219565b6134df602083018a612d5d565b6134ec6040830189612d5d565b6134f96060830188612d5d565b6135066080830187612d5d565b61351360a0830186612d5d565b61352060c0830185612d5d565b6112ee60e0830184612d5d565b604081016132308285612d5d565b60ff8116612c4f565b60808101613552828761353b565b61355f6020830186613219565b61356c6040830185612d5d565b610a376060830184612d5d565b60006105d16131428381565b612c4f81613579565b6080810161359c828761353b565b6135a96020830186613219565b6135b66040830185613585565b610a376060830184613585565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613636576136366135c3565b6040525050565b600061364860405190565b905061365482826135f2565b919050565b60006101c0828403121561366f5761366f600080fd5b61367a6101c061363d565b905060006136888484612cc2565b825250602061369984848301612cc2565b60208301525060406136ad84828501612cc2565b60408301525060606136c184828501612cf4565b60608301525060806136d5848285016131a3565b60808301525060a06136e984828501612cf4565b60a08301525060c06136fd84828501612cf4565b60c08301525060e061371184828501612cf4565b60e08301525061010061372684828501612cf4565b6101008301525061012061373c84828501612cf4565b6101208301525061014061375284828501612cf4565b6101408301525061016061376884828501612cf4565b6101608301525061018061377e848285016131a3565b610180830152506101a061379484828501612cc2565b6101a08301525092915050565b60006101c082840312156137b7576137b7600080fd5b6000612c438484613659565b80357fffffffffffff00000000000000000000000000000000000000000000000000001682826006821015613826576138217fffffffffffff0000000000000000000000000000000000000000000000000000836006036008021b90565b831692505b505092915050565b6fffffffffffffffffffffffffffffffff9182169190811690828201908111156105d1576105d1613265565b80357fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001682826014821015613826576138217fffffffffffffffffffffffffffffffffffffffff000000000000000000000000836014036008021b90565b80357fffffffffffffffffffffffffffffffff000000000000000000000000000000001682826010821015613826576138217fffffffffffffffffffffffffffffffff00000000000000000000000000000000836010036008021b90565b803582826020821015613826576138217fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008021b90565b6fffffffffffffffffffffffffffffffff8116612c4f565b80516101c083019061397c8482613219565b50602082015161398f6020850182613219565b5060408201516139a26040850182613219565b5060608201516139b56060850182612d5d565b5060808201516139c86080850182613952565b5060a08201516139db60a0850182612d5d565b5060c08201516139ee60c0850182612d5d565b5060e0820151613a0160e0850182612d5d565b50610100820151613a16610100850182612d5d565b50610120820151613a2b610120850182612d5d565b50610140820151613a40610140850182612d5d565b50610160820151613a55610160850182612d5d565b50610180820151613a6a610180850182613952565b506101a082015161097c6101a0850182613219565b6101c081016105d1828461396a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60808101613acb8287612d5d565b61355f602083018661353b56fea2646970667358221220e0ac4cfab19cb7c97427e7c850ed5c509238b8485841fe4834625b6cb3b2d04c64736f6c634300081a0033" ); + vm.etch( + _PIMLICO_PAYMASTER_V08, + hex"60806040526004361061018e575f3560e01c80637c627b21116100dc578063c23a5cea11610087578063d547741f11610062578063d547741f14610489578063eb12d61e146104a8578063ec87621c146104c7578063feaf513e146104fa575f5ffd5b8063c23a5cea1461044e578063c399ec881461046d578063d0e30db014610481575f5ffd5b8063a217fddf116100b7578063a217fddf146103e7578063b0d691fe146103fa578063bb9fe6bf1461043a575f5ffd5b80637c627b211461035a5780637dd345cb1461037957806391d1485414610398575f5ffd5b806336568abe1161013c5780635525dcfb116101175780635525dcfb146102ee57806363b241aa1461030d578063736c0d5b1461032c575f5ffd5b806336568abe146102745780634031c20e1461029357806352b7512c146102c1575f5ffd5b8063205c28781161016c578063205c2878146101fb578063248a9ca31461021a5780632f2ff15d14610255575f5ffd5b806301ffc9a7146101925780630396cb60146101c75780630e316ab7146101dc575b5f5ffd5b34801561019d575f5ffd5b506101b16101ac366004612b49565b61051e565b6040516101be9190612b79565b60405180910390f35b6101da6101d5366004612b9e565b6105b6565b005b3480156101e7575f5ffd5b506101da6101f6366004612bed565b61072b565b348015610206575f5ffd5b506101da610215366004612c1c565b610877565b348015610225575f5ffd5b50610248610234366004612c56565b5f9081526020819052604090206001015490565b6040516101be9190612c7a565b348015610260575f5ffd5b506101da61026f366004612c88565b610927565b34801561027f575f5ffd5b506101da61028e366004612c88565b610951565b34801561029e575f5ffd5b506101b16102ad366004612bed565b60026020525f908152604090205460ff1681565b3480156102cc575f5ffd5b506102e06102db366004612cd2565b6109af565b6040516101be929190612d92565b3480156102f9575f5ffd5b50610248610308366004612db2565b6109d1565b348015610318575f5ffd5b50610248610327366004612e26565b610a0d565b348015610337575f5ffd5b506101b1610346366004612bed565b60016020525f908152604090205460ff1681565b348015610365575f5ffd5b506101da610374366004612ed5565b610bc1565b348015610384575f5ffd5b506101da610393366004612fad565b610bdd565b3480156103a3575f5ffd5b506101b16103b2366004612c88565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156103f2575f5ffd5b506102485f81565b348015610405575f5ffd5b5061042d7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff10881565b6040516101be9190613053565b348015610445575f5ffd5b506101da610d92565b348015610459575f5ffd5b506101da610468366004612bed565b610ed0565b348015610478575f5ffd5b50610248610f63565b6101da61101b565b348015610494575f5ffd5b506101da6104a3366004612c88565b6110b8565b3480156104b3575f5ffd5b506101da6104c2366004612bed565b6110dc565b3480156104d2575f5ffd5b506102487f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b348015610505575f5ffd5b50610248610514366004613084565b5f95945050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806105b057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b335f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff161580156106225750335f9081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b1561068657337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161067d9291906130f3565b60405180910390fd5b6040517f0396cb6000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff1081690630396cb609034906106fa90859060040161311a565b5f604051808303818588803b158015610711575f5ffd5b505af1158015610723573d5f5f3e3d5ffd5b505050505050565b335f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff161580156107975750335f9081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b156107f257337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161067d9291906130f3565b73ffffffffffffffffffffffffffffffffffffffff81165f908152600160205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b9061086c908390613128565b60405180910390a150565b5f61088181611222565b6040517f205c287800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108169063205c2878906108f590869086906004016130f3565b5f604051808303815f87803b15801561090c575f5ffd5b505af115801561091e573d5f5f3e3d5ffd5b50505050505050565b5f8281526020819052604090206001015461094181611222565b61094b838361122f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff811633146109a0576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109aa8282611328565b505050565b60605f6109ba6113e1565b6109c5858585611452565b91509150935093915050565b5f670de0b6b3a7640000826109e68587613163565b6109f09088613182565b6109fa9190613163565b610a0491906131c2565b95945050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000060ff168360ff1603610a9857610a9182610a897f000000000000000000000000000000000000000000000000000000000000000c7f00000000000000000000000000000000000000000000000000000000000000016131d5565b60ff16611613565b90506105b0565b5f610ae37f00000000000000000000000000000000000000000000000000000000000000757f00000000000000000000000000000000000000000000000000000000000000016131d5565b90505f610af360e08501856131f2565b610b4060ff7f0000000000000000000000000000000000000000000000000000000000000001167f0000000000000000000000000000000000000000000000000000000000000034613182565b818110610b4f57610b4f61326b565b919091013560f81c9150506001811615156002821615156004831615801590610b8057610b7d6010866131d5565b94505b8215610b9457610b916010866131d5565b94505b8115610ba857610ba56014866131d5565b94505b610bb5878660ff16611613565b98975050505050505050565b610bc96113e1565b610bd6858585858561172d565b5050505050565b335f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16158015610c495750335f9081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b15610ca457337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161067d9291906130f3565b5f5b8281101561094b578160025f868685818110610cc457610cc461326b565b9050602002016020810190610cd99190612bed565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790557f8ff8c5211f68ef53b4bdd15ab2ea6d87be8a3dbf58865bd8325c984057e4fcb4848483818110610d5e57610d5e61326b565b9050602002016020810190610d739190612bed565b83604051610d82929190613298565b60405180910390a1600101610ca6565b335f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16158015610dfe5750335f9081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b15610e5957337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161067d9291906130f3565b7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff10873ffffffffffffffffffffffffffffffffffffffff1663bb9fe6bf6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ebe575f5ffd5b505af115801561094b573d5f5f3e3d5ffd5b5f610eda81611222565b6040517fc23a5cea00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108169063c23a5cea90610f4c908590600401613128565b5f604051808303815f87803b158015610711575f5ffd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff10816906370a0823190610fd7903090600401613128565b602060405180830381865afa158015610ff2573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101691906132be565b905090565b6040517fb760faf900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108169063b760faf990349061108f903090600401613128565b5f604051808303818588803b1580156110a6575f5ffd5b505af1158015610bd6573d5f5f3e3d5ffd5b5f828152602081905260409020600101546110d281611222565b61094b8383611328565b335f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff161580156111485750335f9081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b156111a357337f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161067d9291906130f3565b73ffffffffffffffffffffffffffffffffffffffff81165f9081526001602081905260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055517f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f249061086c908390613128565b61122c8133611915565b50565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16611321575f8381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556112bf3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016105b0565b505f6105b0565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615611321575f8381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016105b0565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff1081614611450576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067d906132dc565b565b60605f8080368161148f61146960e08b018b6131f2565b7f0000000000000000000000000000000000000000000000000000000000000034611983565b9350935093509350821580156114b45750325f9081526002602052604090205460ff16155b156114ed57326040517f55d3ab4600000000000000000000000000000000000000000000000000000000815260040161067d9190613128565b7f000000000000000000000000000000000000000000000000000000000000000160ff168460ff161415801561154957507f000000000000000000000000000000000000000000000000000000000000000060ff168460ff1614155b15611580576040517f654a4f2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60605f7f000000000000000000000000000000000000000000000000000000000000000060ff168660ff16036115c2576115bc8b85858d611a2d565b90925090505b7f000000000000000000000000000000000000000000000000000000000000000160ff168660ff1603611603576115fd868c86868e8e611bbb565b90925090505b909a909950975050505050505050565b5f8083356020850135608086013560a087013560c088013561163860408a018a6131f2565b604051611646929190613334565b60405190819003902061165c60608b018b6131f2565b60405161166a929190613334565b60405190819003902061168060e08c018c6131f2565b5f906116ac8d7f0000000000000000000000000000000000000000000000000000000000000034613182565b926116b993929190613340565b6040516116c7929190613334565b6040519081900381206116e3989796959493929160200161336d565b604051602081830303815290604052805190602001209050804660405160200161170e9291906133e4565b6040516020818303038152906040528051906020012091505092915050565b5f6117388585611cec565b90505f5f6117468286613182565b90505f8361018001516fffffffffffffffffffffffffffffffff166117878386608001516fffffffffffffffffffffffffffffffff168888606001516109d1565b6117919190613182565b90505f84610120015182116117b657818561012001516117b191906133f2565b6117c6565b6101208501516117c690836133f2565b9050611808856020015186610120015184116117e65786604001516117e9565b86515b87610120015185116117fc578751611802565b87604001515b84611ddf565b5f670de0b6b3a764000086606001518761010001516118279190613163565b61183191906131c2565b6101a087015190915073ffffffffffffffffffffffffffffffffffffffff161580159061185d57508281115b1561188457602086015186516101a088015161188492919061187f87866133f2565b611ddf565b855f015173ffffffffffffffffffffffffffffffffffffffff168660a001517f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd27f00000000000000000000000000000000000000000000000000000000000000018960200151878b60600151604051611900949392919061340e565b60405180910390a35050505050505050505050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661197f5780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161067d9291906130f3565b5050565b5f803681611992856001613182565b8610156119cb576040517fcc32193e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8787878181106119de576119de61326b565b919091013560f881901c925060018084161515925060f99190911c9036905f908c908c90611a0d908d90613182565b611a18928290613340565b939d949c509a50919850919650505050505050565b60605f5f5f365f611a3e8989611e37565b93509350935093505f611aa6611a747f00000000000000000000000000000000000000000000000000000000000000008d610a0d565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b90505f611ae88285858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f3e92505050565b73ffffffffffffffffffffffffffffffffffffffff81165f9081526001602052604081205491925060ff90911690611b2282158989611f66565b90508d3573ffffffffffffffffffffffffffffffffffffffff168b7f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd27f00000000000000000000000000000000000000000000000000000000000000005f5f5f604051611b929493929190613457565b60405180910390a360408051602081019091525f81529e909d509b505050505050505050505050565b60605f5f611bc98787611f9c565b90505f611bd9611a748b8b610a0d565b90505f611bea828460c00151611f3e565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260016020908152604080832054918701519087015193945060ff90911692611c2f91841591611f66565b90505f611c3e8d8b888c6126f9565b905082611c535796509450611ce19350505050565b5f611c648a5f5f8a60a001516109d1565b9050808761010001511115611ca5576040517f79183c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010087015115611cd757611cd787608001518f5f016020810190611cca9190612bed565b89516101008b0151611ddf565b5096509450505050505b965096945050505050565b611dcc604051806101c001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81526020015f6fffffffffffffffffffffffffffffffff1681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f6fffffffffffffffffffffffffffffffff1681526020015f73ffffffffffffffffffffffffffffffffffffffff1681525090565b611dd882840184613664565b9392505050565b60405181606052826040528360601b602c526f23b872dd000000000000000000000000600c5260205f6064601c5f895af13d1560015f51141716611e2a57637939f4245f526004601cfd5b5f60605260405250505050565b5f80368160ff7f000000000000000000000000000000000000000000000000000000000000000c16851015611e98576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611ea6600682888a613340565b611eaf91613683565b60d01c90505f611ec3600c6006898b613340565b611ecc91613683565b60d01c9050365f611ee089600c818d613340565b909250905060408114801590611ef7575060418114155b15611f2e576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9299919850965090945092505050565b5f5f5f5f611f4c8686612886565b925092509250611f5c82826128cf565b5090949350505050565b5f60d08265ffffffffffff16901b60a08465ffffffffffff16901b85611f8c575f611f8f565b60015b60ff161717949350505050565b60408051610160810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c082015260e081018290526101008101829052610120810182905261014081019190915260ff7f000000000000000000000000000000000000000000000000000000000000007516821015612050576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80848482816120625761206261326b565b919091013560f81c9150506001808216151590600283161515906004841615159061208d90866136ee565b9450876fffffffffffffffffffffffffffffffff8616886120af8860066136ee565b6fffffffffffffffffffffffffffffffff16926120ce93929190613340565b6120d791613683565b60d01c60208701526120ea6006866136ee565b9450876fffffffffffffffffffffffffffffffff86168861210c8860066136ee565b6fffffffffffffffffffffffffffffffff169261212b93929190613340565b61213491613683565b60d01c60408701526121476006866136ee565b9450876fffffffffffffffffffffffffffffffff8616886121698860146136ee565b6fffffffffffffffffffffffffffffffff169261218893929190613340565b6121919161371a565b60601c60808701526121a46014866136ee565b9450876fffffffffffffffffffffffffffffffff8616886121c68860106136ee565b6fffffffffffffffffffffffffffffffff16926121e593929190613340565b6121ee91613778565b60801c60608701526122016010866136ee565b9450876fffffffffffffffffffffffffffffffff8616886122238860206136ee565b6fffffffffffffffffffffffffffffffff169261224293929190613340565b61224b916137d6565b60a087015261225b6020866136ee565b9450876fffffffffffffffffffffffffffffffff86168861227d8860106136ee565b6fffffffffffffffffffffffffffffffff169261229c93929190613340565b6122a591613778565b60801c60e08701526122b86010866136ee565b9450876fffffffffffffffffffffffffffffffff8616886122da8860146136ee565b6fffffffffffffffffffffffffffffffff16926122f993929190613340565b6123029161371a565b60601c86526123126014866136ee565b5f610100880152945080156123d65761232c8560106136ee565b6fffffffffffffffffffffffffffffffff16871015612377576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b876fffffffffffffffffffffffffffffffff8616886123978860106136ee565b6fffffffffffffffffffffffffffffffff16926123b693929190613340565b6123bf91613778565b60801c6101008701526123d36010866136ee565b94505b5f6101208701528215612498576123ee8560106136ee565b6fffffffffffffffffffffffffffffffff16871015612439576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b876fffffffffffffffffffffffffffffffff8616886124598860106136ee565b6fffffffffffffffffffffffffffffffff169261247893929190613340565b61248191613778565b60801c6101208701526124956010866136ee565b94505b5f610140870152811561255a576124b08560146136ee565b6fffffffffffffffffffffffffffffffff168710156124fb576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b876fffffffffffffffffffffffffffffffff86168861251b8860146136ee565b6fffffffffffffffffffffffffffffffff169261253a93929190613340565b6125439161371a565b60601c6101408701526125576014866136ee565b94505b612578876fffffffffffffffffffffffffffffffff8716818b613340565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050505060c0870152608086015173ffffffffffffffffffffffffffffffffffffffff16612601576040517f33c1dac900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560a001515f0361263e576040517f5b33c69600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818015612664575061014086015173ffffffffffffffffffffffffffffffffffffffff16155b1561269b576040517f497189f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560c00151516040141580156126b757508560c0015151604114155b156126ee576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505092915050565b60605f612705866129d0565b61270e876129ff565b6127189190613182565b90505f8460e001516fffffffffffffffffffffffffffffffff1661273b88612a1c565b6127499060a08a0135613182565b6127539190613182565b604080516101c081019091529091508061277060208a018a612bed565b73ffffffffffffffffffffffffffffffffffffffff168152602001866080015173ffffffffffffffffffffffffffffffffffffffff168152602001865f015173ffffffffffffffffffffffffffffffffffffffff1681526020018660a00151815260200186606001516fffffffffffffffffffffffffffffffff1681526020018781526020015f81526020015f815260200185815260200186610100015181526020018381526020018281526020018661012001516fffffffffffffffffffffffffffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff1681525060405160200161286b919061393f565b60405160208183030381529060405292505050949350505050565b5f5f5f83516041036128bd576020840151604085015160608601515f1a6128af88828585612a2b565b9550955095505050506128c8565b505081515f91506002905b9250925092565b5f8260038111156128e2576128e261394e565b036128eb575050565b60018260038111156128ff576128ff61394e565b03612936576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561294a5761294a61394e565b03612983576040517ffce698f700000000000000000000000000000000000000000000000000000000815261067d908290600401612c7a565b60038260038111156129975761299761394e565b0361197f57806040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260040161067d9190612c7a565b5f6129de60e08301836131f2565b6129ed91603491602491613340565b6129f691613778565b60801c92915050565b5f6fffffffffffffffffffffffffffffffff6080830135166105b0565b5f6105b0826080013560801c90565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612a6457505f91506003905082612b06565b5f6001888888886040515f8152602001604052604051612a87949392919061397b565b6020604051602081039080840390855afa158015612aa7573d5f5f3e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612afd57505f925060019150829050612b06565b92505f91508190505b9450945094915050565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b811461122c575f5ffd5b80356105b081612b10565b5f60208284031215612b5c57612b5c5f5ffd5b5f612b678484612b3e565b949350505050565b8015155b82525050565b602081016105b08284612b6f565b63ffffffff8116612b34565b80356105b081612b87565b5f60208284031215612bb157612bb15f5ffd5b5f612b678484612b93565b5f73ffffffffffffffffffffffffffffffffffffffff82166105b0565b612b3481612bbc565b80356105b081612bd9565b5f60208284031215612c0057612c005f5ffd5b5f612b678484612be2565b80612b34565b80356105b081612c0b565b5f5f60408385031215612c3057612c305f5ffd5b5f612c3b8585612be2565b9250506020612c4c85828601612c11565b9150509250929050565b5f60208284031215612c6957612c695f5ffd5b5f612b678484612c11565b80612b73565b602081016105b08284612c74565b5f5f60408385031215612c9c57612c9c5f5ffd5b5f612ca78585612c11565b9250506020612c4c85828601612be2565b5f6101208284031215612ccc57612ccc5f5ffd5b50919050565b5f5f5f60608486031215612ce757612ce75f5ffd5b833567ffffffffffffffff811115612d0057612d005f5ffd5b612d0c86828701612cb8565b9350506020612d1d86828701612c11565b9250506040612d2e86828701612c11565b9150509250925092565b8281835e505f910152565b5f612d4c825190565b808452602084019350612d63818560208601612d38565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b60408082528101612da38185612d43565b9050611dd86020830184612c74565b5f5f5f5f60808587031215612dc857612dc85f5ffd5b5f612dd38787612c11565b9450506020612de487828801612c11565b9350506040612df587828801612c11565b9250506060612e0687828801612c11565b91505092959194509250565b60ff8116612b34565b80356105b081612e12565b5f5f60408385031215612e3a57612e3a5f5ffd5b5f612e458585612e1b565b925050602083013567ffffffffffffffff811115612e6457612e645f5ffd5b612c4c85828601612cb8565b6003811061122c575f5ffd5b80356105b081612e70565b5f5f83601f840112612e9a57612e9a5f5ffd5b50813567ffffffffffffffff811115612eb457612eb45f5ffd5b602083019150836001820283011115612ece57612ece5f5ffd5b9250929050565b5f5f5f5f5f60808688031215612eec57612eec5f5ffd5b5f612ef78888612e7c565b955050602086013567ffffffffffffffff811115612f1657612f165f5ffd5b612f2288828901612e87565b94509450506040612f3588828901612c11565b9250506060612f4688828901612c11565b9150509295509295909350565b5f5f83601f840112612f6657612f665f5ffd5b50813567ffffffffffffffff811115612f8057612f805f5ffd5b602083019150836020820283011115612ece57612ece5f5ffd5b801515612b34565b80356105b081612f9a565b5f5f5f60408486031215612fc257612fc25f5ffd5b833567ffffffffffffffff811115612fdb57612fdb5f5ffd5b612fe786828701612f53565b93509350506020612d2e86828701612fa2565b5f6105b073ffffffffffffffffffffffffffffffffffffffff831661301d565b90565b73ffffffffffffffffffffffffffffffffffffffff1690565b5f6105b082612ffa565b5f6105b082613036565b612b7381613040565b602081016105b0828461304a565b6fffffffffffffffffffffffffffffffff8116612b34565b80356105b081613061565b5f5f5f5f5f60a0868803121561309b5761309b5f5ffd5b5f6130a68888612c11565b95505060206130b788828901612c11565b94505060406130c888828901613079565b93505060606130d988828901612c11565b9250506080612f4688828901612c11565b612b7381612bbc565b6040810161310182856130ea565b611dd86020830184612c74565b63ffffffff8116612b73565b602081016105b0828461310e565b602081016105b082846130ea565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810280821583820485141761317b5761317b613136565b5092915050565b808201808211156105b0576105b0613136565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826131d0576131d0613195565b500490565b60ff9182169190811690828201908111156105b0576105b0613136565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe136859003018112613229576132295f5ffd5b80840192508235915067ffffffffffffffff821115613249576132495f5ffd5b602083019250600182023603831315613263576132635f5ffd5b509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604081016132a682856130ea565b611dd86020830184612b6f565b80516105b081612c0b565b5f602082840312156132d1576132d15f5ffd5b5f612b6784846132b3565b602080825281016105b081601581527f53656e646572206e6f7420456e747279506f696e740000000000000000000000602082015260400190565b82818337505f910152565b5f61332e838584613317565b50500190565b5f612b67828486613322565b5f5f85851115613351576133515f5ffd5b83861115613360576133605f5ffd5b5050820193919092039150565b610100810161337c828b6130ea565b613389602083018a612c74565b6133966040830189612c74565b6133a36060830188612c74565b6133b06080830187612c74565b6133bd60a0830186612c74565b6133ca60c0830185612c74565b6133d760e0830184612c74565b9998505050505050505050565b604081016131018285612c74565b818103818111156105b0576105b0613136565b60ff8116612b73565b6080810161341c8287613405565b61342960208301866130ea565b6134366040830185612c74565b610a046060830184612c74565b5f6105b061301a8381565b612b7381613443565b608081016134658287613405565b61347260208301866130ea565b61347f604083018561344e565b610a04606083018461344e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff821117156134fd576134fd61348c565b6040525050565b5f61350e60405190565b905061351a82826134b9565b919050565b5f6101c08284031215613533576135335f5ffd5b61353e6101c0613504565b90505f61354b8484612be2565b825250602061355c84848301612be2565b602083015250604061357084828501612be2565b604083015250606061358484828501612c11565b606083015250608061359884828501613079565b60808301525060a06135ac84828501612c11565b60a08301525060c06135c084828501612c11565b60c08301525060e06135d484828501612c11565b60e0830152506101006135e984828501612c11565b610100830152506101206135ff84828501612c11565b6101208301525061014061361584828501612c11565b6101408301525061016061362b84828501612c11565b6101608301525061018061364184828501613079565b610180830152506101a061365784828501612be2565b6101a08301525092915050565b5f6101c08284031215613678576136785f5ffd5b5f612b67848461351f565b80357fffffffffffff000000000000000000000000000000000000000000000000000016828260068210156136e6576136e17fffffffffffff0000000000000000000000000000000000000000000000000000836006036008021b90565b831692505b505092915050565b6fffffffffffffffffffffffffffffffff9182169190811690828201908111156105b0576105b0613136565b80357fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016828260148210156136e6576136e17fffffffffffffffffffffffffffffffffffffffff000000000000000000000000836014036008021b90565b80357fffffffffffffffffffffffffffffffff0000000000000000000000000000000016828260108210156136e6576136e17fffffffffffffffffffffffffffffffff00000000000000000000000000000000836010036008021b90565b8035828260208210156136e6576136e17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008021b90565b6fffffffffffffffffffffffffffffffff8116612b73565b80516101c083019061383c84826130ea565b50602082015161384f60208501826130ea565b50604082015161386260408501826130ea565b5060608201516138756060850182612c74565b5060808201516138886080850182613812565b5060a082015161389b60a0850182612c74565b5060c08201516138ae60c0850182612c74565b5060e08201516138c160e0850182612c74565b506101008201516138d6610100850182612c74565b506101208201516138eb610120850182612c74565b50610140820151613900610140850182612c74565b50610160820151613915610160850182612c74565b5061018082015161392a610180850182613812565b506101a082015161094b6101a08501826130ea565b6101c081016105b0828461382a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b608081016139898287612c74565b613429602083018661340556fea26469706673582212208a15a0763d0e9e3763499efb24664c89aecc3b170e7b24ffc642014b6ca6baa764736f6c634300081c0033" + ); vm.etch( _GNOSIS_SAFE_v1_4_1, hex"6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a03231461156b578063f698da25146115bc578063f8dc5dd9146115e7578063ffa1ad741461166257610226565b8063e19a9dd9146112bf578063e318b52b14611310578063e75235b8146113a1578063e86637db146113cc57610226565b8063cc2f8452116100d1578063cc2f84521461100c578063d4d9bdcd146110d9578063d8d11f7814611114578063e009cfde1461124e57610226565b8063affed0e014610d89578063b4faba0914610db4578063b63e800d14610e9c57610226565b80635624b25b1161016f5780636a7612021161013e5780636a761202146109895780637d83297414610b45578063934f3a1114610bb4578063a0e67e2b14610d1d57610226565b80635624b25b146107f05780635ae6bd37146108ae578063610b5925146108fd578063694e80c31461094e57610226565b80632f54bf6e116101ab5780632f54bf6e146104c85780633408e4701461052f578063468721a71461055a5780635229073f1461066f57610226565b80630d582f131461029357806312fb68e0146102ee5780632d9ad53d1461046157610226565b36610226573373ffffffffffffffffffffffffffffffffffffffff167f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d346040518082815260200191505060405180910390a2005b34801561023257600080fd5b5060007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b905080548061026757600080f35b36600080373360601b365260008060143601600080855af13d6000803e8061028e573d6000fd5b3d6000f35b34801561029f57600080fd5b506102ec600480360360408110156102b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506116f2565b005b3480156102fa57600080fd5b5061045f6004803603608081101561031157600080fd5b81019080803590602001909291908035906020019064010000000081111561033857600080fd5b82018360208201111561034a57600080fd5b8035906020019184600183028401116401000000008311171561036c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156103cf57600080fd5b8201836020820111156103e157600080fd5b8035906020019184600183028401116401000000008311171561040357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050611ad8565b005b34801561046d57600080fd5b506104b06004803603602081101561048457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506123d6565b60405180821515815260200191505060405180910390f35b3480156104d457600080fd5b50610517600480360360208110156104eb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124a8565b60405180821515815260200191505060405180910390f35b34801561053b57600080fd5b5061054461257a565b6040518082815260200191505060405180910390f35b34801561056657600080fd5b506106576004803603608081101561057d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105c457600080fd5b8201836020820111156105d657600080fd5b803590602001918460018302840111640100000000831117156105f857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190505050612587565b60405180821515815260200191505060405180910390f35b34801561067b57600080fd5b5061076c6004803603608081101561069257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156106d957600080fd5b8201836020820111156106eb57600080fd5b8035906020019184600183028401116401000000008311171561070d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff16906020019092919050505061278d565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107b4578082015181840152602081019050610799565b50505050905090810190601f1680156107e15780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156107fc57600080fd5b506108336004803603604081101561081357600080fd5b8101908080359060200190929190803590602001909291905050506127c3565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610873578082015181840152602081019050610858565b50505050905090810190601f1680156108a05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108ba57600080fd5b506108e7600480360360208110156108d157600080fd5b810190808035906020019092919050505061284a565b6040518082815260200191505060405180910390f35b34801561090957600080fd5b5061094c6004803603602081101561092057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612862565b005b34801561095a57600080fd5b506109876004803603602081101561097157600080fd5b8101908080359060200190929190505050612bea565b005b610b2d60048036036101408110156109a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109e757600080fd5b8201836020820111156109f957600080fd5b80359060200191846001830284011164010000000083111715610a1b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610aa757600080fd5b820183602082011115610ab957600080fd5b80359060200191846001830284011164010000000083111715610adb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612d24565b60405180821515815260200191505060405180910390f35b348015610b5157600080fd5b50610b9e60048036036040811015610b6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613253565b6040518082815260200191505060405180910390f35b348015610bc057600080fd5b50610d1b60048036036060811015610bd757600080fd5b810190808035906020019092919080359060200190640100000000811115610bfe57600080fd5b820183602082011115610c1057600080fd5b80359060200191846001830284011164010000000083111715610c3257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610c9557600080fd5b820183602082011115610ca757600080fd5b80359060200191846001830284011164010000000083111715610cc957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613278565b005b348015610d2957600080fd5b50610d32613307565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610d75578082015181840152602081019050610d5a565b505050509050019250505060405180910390f35b348015610d9557600080fd5b50610d9e6134b0565b6040518082815260200191505060405180910390f35b348015610dc057600080fd5b50610e9a60048036036040811015610dd757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610e1457600080fd5b820183602082011115610e2657600080fd5b80359060200191846001830284011164010000000083111715610e4857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506134b6565b005b348015610ea857600080fd5b5061100a6004803603610100811015610ec057600080fd5b8101908080359060200190640100000000811115610edd57600080fd5b820183602082011115610eef57600080fd5b80359060200191846020830284011164010000000083111715610f1157600080fd5b909192939192939080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610f5c57600080fd5b820183602082011115610f6e57600080fd5b80359060200191846001830284011164010000000083111715610f9057600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134d8565b005b34801561101857600080fd5b506110656004803603604081101561102f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613696565b60405180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156110c45780820151818401526020810190506110a9565b50505050905001935050505060405180910390f35b3480156110e557600080fd5b50611112600480360360208110156110fc57600080fd5b81019080803590602001909291905050506139f9565b005b34801561112057600080fd5b50611238600480360361014081101561113857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561117f57600080fd5b82018360208201111561119157600080fd5b803590602001918460018302840111640100000000831117156111b357600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b98565b6040518082815260200191505060405180910390f35b34801561125a57600080fd5b506112bd6004803603604081101561127157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613bc5565b005b3480156112cb57600080fd5b5061130e600480360360208110156112e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f4c565b005b34801561131c57600080fd5b5061139f6004803603606081101561133357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614138565b005b3480156113ad57600080fd5b506113b6614796565b6040518082815260200191505060405180910390f35b3480156113d857600080fd5b506114f060048036036101408110156113f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561143757600080fd5b82018360208201111561144957600080fd5b8035906020019184600183028401116401000000008311171561146b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506147a0565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611530578082015181840152602081019050611515565b50505050905090810190601f16801561155d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561157757600080fd5b506115ba6004803603602081101561158e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614948565b005b3480156115c857600080fd5b506115d161499f565b6040518082815260200191505060405180910390f35b3480156115f357600080fd5b506116606004803603606081101561160a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614a1d565b005b34801561166e57600080fd5b50611677614e46565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156116b757808201518184015260208101905061169c565b50505050905090810190601f1680156116e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6116fa614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156117645750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561179c57503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b61180e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461190f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a28060045414611ad457611ad381612bea565b5b5050565b611aec604182614f2290919063ffffffff16565b82511015611b62576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808060008060005b868110156123ca57611b7e8882614f5c565b80945081955082965050505060008460ff1614156120035789898051906020012014611c12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323700000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260001c9450611c2c604188614f2290919063ffffffff16565b8260001c1015611ca4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8751611cbd60208460001c614f8b90919063ffffffff16565b1115611d31576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006020838a01015190508851611d6782611d5960208760001c614f8b90919063ffffffff16565b614f8b90919063ffffffff16565b1115611ddb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60606020848b010190506320c13b0b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168773ffffffffffffffffffffffffffffffffffffffff166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015611e7d578082015181840152602081019050611e62565b50505050905090810190601f168015611eaa5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015611ee3578082015181840152602081019050611ec8565b50505050905090810190601f168015611f105780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015611f2f57600080fd5b505afa158015611f43573d6000803e3d6000fd5b505050506040513d6020811015611f5957600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ffc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5050612248565b60018460ff161415612117578260001c94508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120a057506000600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c81526020019081526020016000205414155b612112576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b612247565b601e8460ff1611156121df5760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156121ce573d6000803e3d6000fd5b505050602060405103519450612246565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612239573d6000803e3d6000fd5b5050506020604051035194505b5b5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1611801561230f5750600073ffffffffffffffffffffffffffffffffffffffff16600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156123485750600173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b6123ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8495508080600101915050611b6c565b50505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff16141580156124a15750600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156125735750600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000804690508091505090565b6000600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156126525750600073ffffffffffffffffffffffffffffffffffffffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b6126c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6126f1858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b90508015612741573373ffffffffffffffffffffffffffffffffffffffff167f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb860405160405180910390a2612785565b3373ffffffffffffffffffffffffffffffffffffffff167facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37560405160405180910390a25b949350505050565b6000606061279d86868686612587565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006020830267ffffffffffffffff811180156127e157600080fd5b506040519080825280601f01601f1916602001820160405280156128145781602001600182028036833780820191505090505b50905060005b8381101561283f5780850154806020830260208501015250808060010191505061281a565b508091505092915050565b60076020528060005260406000206000915090505481565b61286a614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128d45750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b612946576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844060405160405180910390a250565b612bf2614e7f565b600354811115612c6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001811015612ce1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b806004819055507f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c936004546040518082815260200191505060405180910390a150565b6000806000612d3e8e8e8e8e8e8e8e8e8e8e6005546147a0565b905060056000815480929190600101919050555080805190602001209150612d67828286613278565b506000612d72614ff6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612f58578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115612e1557fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528d8d82818152602001925080828437600081840152601f19601f820116905080830192505050838103825285818151815260200191508051906020019080838360005b83811015612ee7578082015181840152602081019050612ecc565b50505050905090810190601f168015612f145780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015612f3f57600080fd5b505af1158015612f53573d6000803e3d6000fd5b505050505b6101f4612f7f6109c48b01603f60408d0281612f7057fe5b0461502790919063ffffffff16565b015a1015612ff5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60005a905061305e8f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e60008d14613053578e613059565b6109c45a035b614faa565b93506130735a8261504190919063ffffffff16565b90508380613082575060008a14155b8061308e575060008814155b613100576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008089111561311a57613117828b8b8b8b615061565b90505b841561315d57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e826040518082815260200191505060405180910390a2613196565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040518082815260200191505060405180910390a25b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613242578073ffffffffffffffffffffffffffffffffffffffff16639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b15801561322957600080fd5b505af115801561323d573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b6008602052816000526040600020602052806000526040600020600091509150505481565b60006004549050600081116132f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61330184848484611ad8565b50505050565b6060600060035467ffffffffffffffff8111801561332457600080fd5b506040519080825280602002602001820160405280156133535781602001602082028036833780820191505090505b50905060008060026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146134a757808383815181106133fe57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081806001019250506133bd565b82935050505090565b60055481565b600080825160208401855af4806000523d6020523d600060403e60403d016000fd5b6135238a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505089615267565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146135615761356084615767565b5b6135af8787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050615838565b60008211156135c9576135c782600060018685615061565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b8960405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281038252878782818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a250505050505050505050565b60606000600173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806136da57506136d9846123d6565b5b61374c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600083116137c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8267ffffffffffffffff811180156137d957600080fd5b506040519080825280602002602001820160405280156138085781602001602082028036833780820191505090505b5091506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156138da5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b80156138e557508381105b156139a057818382815181106138f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508080600101915050613870565b600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146139ee578260018203815181106139e357fe5b602002602001015191505b808352509250929050565b600073ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613afb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16817ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c60405160405180910390a350565b6000613bad8c8c8c8c8c8c8c8c8c8c8c6147a0565b8051906020012090509b9a5050505050505050505050565b613bcd614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015613c375750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613ca9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613da9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427660405160405180910390a25050565b613f54614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146140c6578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561401857600080fd5b505afa15801561402c573d6000803e3d6000fd5b505050506040513d602081101561404257600080fd5b81019080805190602001909291905050506140c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475333303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b60007f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa260405160405180910390a25050565b614140614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156141aa5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156141e257503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b614254576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614355576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156143bf5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614431576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614531576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28073ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a2505050565b6000600454905090565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a815260200189815260200188600181111561483157fe5b81526020018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b6148bd61499f565b8360405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101847effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018381526020018281526020019450505050506040516020818303038152906040529150509b9a5050505050505050505050565b614950614e7f565b61495981615767565b8073ffffffffffffffffffffffffffffffffffffffff167f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b060405160405180910390a250565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b6149cd61257a565b30604051602001808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405160208183030381529060405280519060200120905090565b614a25614e7f565b806001600354031015614aa0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015614b0a5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614b7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614c7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360008154809291906001900391905055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28060045414614e4157614e4081612bea565b5b505050565b6040518060400160405280600581526020017f312e342e3100000000000000000000000000000000000000000000000000000081525081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614f20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b600080831415614f355760009050614f56565b6000828402905082848281614f4657fe5b0414614f5157600080fd5b809150505b92915050565b60008060008360410260208101860151925060408101860151915060ff60418201870151169350509250925092565b600080828401905083811015614fa057600080fd5b8091505092915050565b6000600180811115614fb857fe5b836001811115614fc457fe5b1415614fdd576000808551602087018986f49050614fed565b600080855160208701888a87f190505b95945050505050565b6000807f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b9050805491505090565b6000818310156150375781615039565b825b905092915050565b60008282111561505057600080fd5b600082840390508091505092915050565b600080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461509e57826150a0565b325b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156151b85761510a3a86106150e7573a6150e9565b855b6150fc888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050506151b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61525d565b6151dd856151cf888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91506151ea848284615b0e565b61525c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5095945050505050565b6000600454146152df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8151811115615356576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60018110156153cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006001905060005b83518110156156d35760008482815181106153ed57fe5b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156154615750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561549957503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156154d157508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b615543576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614615644576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508092505080806001019150506153d6565b506001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550825160038190555081600481905550505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415615809576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475334303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b90508181555050565b600073ffffffffffffffffffffffffffffffffffffffff1660016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461593a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001806000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614615b0a576159f682615bd2565b615a68576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b615a978260008360017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b615b09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5050565b60008063a9059cbb8484604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602060008251602084016000896127105a03f13d60008114615bb55760208114615bbd5760009350615bc8565b819350615bc8565b600051158215171593505b5050509392505050565b600080823b90506000811191505091905056fea264697066735822122057398fa72884cf9a6cb78aab2fb58a6b927f0e9d97d75b015daaee0959a153bf64736f6c63430007060033" @@ -209,6 +230,10 @@ contract BenchmarkTest is BaseTest { _ADD_MODULES_LIB, hex"608060405234801561001057600080fd5b506004361061002b5760003560e01c80638d0dc49f14610030575b600080fd5b61004361003e36600461011a565b610045565b005b805b8015610115573063610b592584846100606001866101be565b81811061006f5761006f6101d7565b90506020020160208101906100849190610206565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b1580156100ea57600080fd5b505af11580156100fe573d6000803e3d6000fd5b50505050808061010d90610243565b915050610047565b505050565b6000806020838503121561012d57600080fd5b823567ffffffffffffffff8082111561014557600080fd5b818501915085601f83011261015957600080fd5b81358181111561016857600080fd5b8660208260051b850101111561017d57600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156101d1576101d161018f565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561021857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461023c57600080fd5b9392505050565b6000816102525761025261018f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea264697066735822122022cfe34f0de69ff92f9c49103555ee9f9c6ff5b0582e357de6f64f2a2bc215aa64736f6c63430008170033" ); + vm.etch( + _OPF7702, + hex"60806040526004361015610020575b361561001657005b61001e613649565b005b5f3560e01c806223de291461039a57806301ffc9a7146103955780630836acf41461039057806311d2c2331461038b57806312aaac7014610386578063150b7a02146103815780631626ba7e1461037c57806317f976721461037757806319822f7c146103725780631a37ef231461036d578063233640311461036857806327258b221461036357806327dba4431461035e57806328495877146103595780632ad8c0e5146103545780632eb2bb221461034f5780632ef1f99b1461034a57806333a0c47e1461034557806334fcd5be146103405780633a5dbdc21461033b57806341f60007146103365780634223b5c2146103315780634894c62a1461032c5780634c9db5b014610327578063537f80b314610322578063572f22101461031d578063584465f2146103185780637613e7ba1461031357806378daf0d11461030e5780637b49fa19146103095780637c2a5d471461030457806384b0196e146102ff578063880e9cd7146102fa5780638bda7f58146102f557806396acbf3f146102f0578063a580daad146102eb578063af640d0f1461028c578063b0d691fe146102e6578063b61d27f6146102e1578063b9ba2c38146102dc578063ba2ba576146102d7578063bc197c81146102d2578063d0336a2b146102cd578063d03c7914146102c8578063d087d288146102c3578063d670520f146102be578063db518e26146102b9578063df59e82d146102b4578063e0377b17146102af578063e55a504d146102aa578063e5adda71146102a5578063e9ae5c53146102a0578063f23a6e611461029b578063f4032c4314610296578063faba56d8146102915763fac750e00361000e575b611bff565b6127a7565b61254f565b6124ec565b612485565b61236d565b612252565b6121d5565b612197565b61215f565b6120e6565b61201a565b611ff2565b611ec8565b611ded565b611d44565b611cef565b611c74565b611c28565b611bbb565b611b3d565b611af9565b611ab5565b6119b8565b6118e7565b6118ac565b6117fc565b6117d5565b6116e8565b611651565b611582565b611501565b611472565b61135e565b611342565b6112f5565b61124f565b611233565b611133565b611011565b610fbe565b610f60565b610f16565b610ea1565b610c44565b610bc3565b610b03565b610abf565b610a89565b6109d4565b6107be565b6105db565b6105a5565b61049a565b6103fa565b6001600160a01b031690565b6001600160a01b038116036103bc57565b5f80fd5b35906103cb826103ab565b565b9181601f840112156103bc578235916001600160401b0383116103bc57602083818601950101116103bc57565b346103bc5760c03660031901126103bc576104166004356103ab565b6104216024356103ab565b61042c6044356103ab565b6084356001600160401b0381116103bc5761044b9036906004016103cd565b505060a4356001600160401b0381116103bc5761001e9036906004016103cd565b600435906001600160e01b0319821682036103bc57565b604435906001600160e01b0319821682036103bc57565b346103bc5760203660031901126103bc576105086001600160e01b03196104bf61046c565b166301ffc9a760e01b8114908115610560575b811561054f575b811561053e575b811561052d575b811561051c575b811561050c575b5060405190151581529081906020820190565b0390f35b6223de2960e01b1490505f6104f5565b630271189760e51b811491506104ee565b630a85bd0160e11b811491506104e7565b633992254760e01b811491506104e0565b630b135d3f60e11b811491506104d9565b6306608bdf60e21b811491506104d2565b5f525f516020615df15f395f51905f5260205260405f2090565b5f525f516020615eb15f395f51905f5260205260405f2090565b346103bc5760203660031901126103bc576004355f525f516020615e315f395f51905f52602052602060405f2054604051908152f35b346103bc5760203660031901126103bc576004356105f8816103ab565b610600613677565b7f000000000000000000000000000000000000000000000000000000000002a3006001600160a01b0361063282613ff4565b16916001600160a01b038116908184146106cc576106546106759215156136d1565b5f516020615f715f395f51905f5254600160ff1b81166106be575b50614bc5565b5f516020615f715f395f51905f52556001600160a01b039061069690613ff4565b16907f253e92d60f46dbf5d74b1618c38a686d970f53cd44146daeb53bb04b156adc705f80a3005b6001600160a01b031661066f565b630b656f6360e01b5f5260045ffd5b634e487b7160e01b5f52602160045260245ffd5b600411156106f957565b6106db565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9061010060e06107aa938051610737816106ef565b84526020810151151560208501526107586040820151604086019015159052565b60608181015115159085015260808181015165ffffffffffff169085015260a08181015165ffffffffffff169085015260c08181015165ffffffffffff16908501520151918160e082015201906106fe565b90565b9060206107aa928181520190610722565b346103bc5760203660031901126103bc576004356107da6127d3565b505f525f516020615df15f395f51905f5260205261050860405f206108ae600160405192610807846108d3565b6108a861089f825460ff811661081c816106ef565b8752600881901c60ff1615156020880152610841601082901c60ff1615156040890152565b610855601882901c60ff1615156060890152565b61087361086a8260201c65ffffffffffff1690565b6080890161280f565b6108916108888260501c65ffffffffffff1690565b60a0890161280f565b60801c65ffffffffffff1690565b60c0860161280f565b016128d5565b60e0820152604051918291826107ad565b634e487b7160e01b5f52604160045260245ffd5b61010081019081106001600160401b038211176108ef57604052565b6108bf565b60c081019081106001600160401b038211176108ef57604052565b604081019081106001600160401b038211176108ef57604052565b606081019081106001600160401b038211176108ef57604052565b601f909101601f19168101906001600160401b038211908210176108ef57604052565b6001600160401b0381116108ef57601f01601f191660200190565b92919261098f82610968565b9161099d6040519384610945565b8294818452818301116103bc578281602093845f960137010152565b9080601f830112156103bc578160206107aa93359101610983565b346103bc5760803660031901126103bc576109f06004356103ab565b6109fb6024356103ab565b6064356001600160401b0381116103bc57610a1a9036906004016109b9565b50604051630a85bd0160e11b8152602090f35b9060406003198301126103bc5760043591602435906001600160401b0382116103bc576107aa916004016109b9565b9190916040818403126103bc5780359260208201356001600160401b0381116103bc576107aa92016109b9565b346103bc576020610aa2610a9c36610a2d565b906128f0565b6040516001600160e01b03199091168152f35b5f9103126103bc57565b346103bc575f3660031901126103bc576040517f0000000000000000000000007702080183ee36ef64f317815185d89bfc6b239a6001600160a01b03168152602090f35b346103bc5760603660031901126103bc576004356001600160401b0381116103bc5761012060031982360301126103bc5760243590604435906001600160a01b03610b6d7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108614243565b163303610bb45761050892610b84916004016139dd565b9080610b9c575b506040519081529081906020820190565b5f80808093335af150610bad613ab8565b505f610b8b565b6306facdbd60e21b5f5260045ffd5b346103bc5760203660031901126103bc57600435610be0816103ab565b610be8613677565b5f516020615e115f395f51905f52545f5260601b600c525f515f516020615e115f395f51905f52555f80f35b60809060031901126103bc5760043590602435610c30816103ab565b906044359060643560078110156103bc5790565b346103bc57610c5236610c14565b929190610c5d613677565b825f525f516020615df15f395f51905f52602052610c7d60405f20613ae7565b610c8682613b1e565b610c8f81613b3d565b825f525f516020615eb15f395f51905f5260205260405f20935f94610cb381615301565b6001600160a01b0385169690879068fbb67fda52d4bfb8bf8214610e94578115610e83575b805460208290526001600160601b038116928315610dc4575b805f5260405f2093845415610d8b5750505050505b80610d6a575b15610d5b576003610d2f5f516020615ef15f395f51905f529560015f9401612c10565b610d398482613b44565b8460018201558260028201550155610d5660405192839283612939565b0390a3005b631e36b0e560e31b5f5260045ffd5b6040610d7583614022565b1115610d0c575b63155176b960e11b5f5260045ffd5b90919293945060011c9060019482860190558115610db45760601b908301556002019055610d06565b91505060601b6003179055610d06565b92508060601c908115610e7357838214610e6a5760018301805460601c908115610e585750848114610e4e576002840190815460601c918215610e3b5750858214610e30576007935f52600160405f20555f52600260405f20555f52600360405f205517600792610cf1565b505050505050610d06565b9650505050505060601b90556001610d06565b5050505050610d06565b95505050505060601b90556001610d06565b50505050610d06565b5050915060601b90556001610d06565b68fbb67fda52d4bfb8bf9150610cd8565b63f5a267f15f526004601cfd5b346103bc5760203660031901126103bc57600435805f525f516020615df15f395f51905f5260205265ffffffffffff60405f205460201c1615801590610eef575b6040519015158152602090f35b505f525f516020615df15f395f51905f5260205261050860ff60405f205460081c16610ee2565b346103bc5760403660031901126103bc576020610f56602435600435610f3b826103ab565b5f525f516020615eb15f395f51905f52835260405f20613b5c565b6040519015158152f35b346103bc575f3660031901126103bc57610508604051610f81604082610945565b601c81527b6f70656e666f72742e626173654163636f756e742e373730322e763160201b60208201526040519182916020835260208301906106fe565b346103bc5760603660031901126103bc576020610f56600435602435610fe3816103ab565b610feb610483565b915f525f516020615dd15f395f51905f52845260405f209160e01c9060601b1790613beb565b346103bc5761101f36610c14565b92919061102a613677565b825f525f516020615df15f395f51905f5260205261104a60405f20613ae7565b61105382613b1e565b61105c81613b3d565b825f525f516020615eb15f395f51905f5260205260405f209161107f8184613b5c565b156110d2575f60036110a28360015f516020615ef15f395f51905f529701612c10565b6110ac8882613b44565b8460018201558260028201550155610d5660405192839260018060a01b03169683612939565b6315a7e52960e11b5f5260045ffd5b9060206003198301126103bc576004356001600160401b0381116103bc5760040182601f820112156103bc578035926001600160401b0384116103bc576020808301928560051b0101116103bc579190565b346103bc57611141366110e1565b604051918291634c893e2560e11b835280604484013060048601526040602486015252606483019060648160051b8501019280925f915b8383106111f957865f8180890381837f00000000000000000000000000000000000000000000000000000000000697806001600160a01b03165af180156111f45761001e915f916111d2575b506111cd613ccc565b613d63565b6111ee91503d805f833e6111e68183610945565b8101906129cc565b826111c4565b612ac9565b9193955091936020806112216001936063198b820301875261121b8a87612a97565b90612a77565b97019301930190928695949293611178565b346103bc5760203660031901126103bc5761001e600435612afb565b346103bc5761125d366110e1565b611265613677565b5f5b81811061127057005b6112b66112b26112ac611284848688612b96565b61128d81612bbd565b906112a16020820135916040810190612bc7565b93905a943691610983565b91613fc8565b1590565b6112c257600101611267565b600182145f03611cdf576112d4613fda565b604051635a15467560e01b81529182916112f19160048401612bf9565b0390fd5b346103bc575f3660031901126103bc5760206113307f000000000000000000000000000000000000000000000000000000000002a300613ff4565b6040516001600160a01b039091168152f35b346103bc5760203660031901126103bc5761001e600435612c25565b346103bc5760203660031901126103bc5760043561137a6127d3565b505f525f516020615e315f395f51905f5260205260405f2054805f525f516020615df15f395f51905f5260205260405f20906114516001604051936113be856108d3565b6108a8611448825460ff81166113d3816106ef565b8852600881901c60ff16151560208901526113f8601082901c60ff16151560408a0152565b61140c601882901c60ff16151560608a0152565b61142a6114218260201c65ffffffffffff1690565b60808a0161280f565b61089161143f8260501c65ffffffffffff1690565b60a08a0161280f565b60c0870161280f565b60e08301526105086040519283928352604060208401526040830190610722565b346103bc5760203660031901126103bc5760043561148e613677565b805f525f516020615df15f395f51905f5260205260405f20805460ff8160081c166114e45761ff0019166101001790557f4cb2301e6ffcd59544d8b92076d92a7299167fcbe0e7e13dce8c89a87d67319e5f80a2005b631fd5727f60e01b5f5260045ffd5b908160c09103126103bc5790565b346103bc5760603660031901126103bc576004356001600160401b0381116103bc576115319036906004016114f3565b6024356001600160401b0381116103bc5760209161155661155f9236906004016114f3565b60443591612dcf565b604051908152f35b65ffffffffffff8116036103bc57565b35906103cb82611567565b346103bc5760603660031901126103bc576004357f0ecffcf298ec5186cccde89a3257343a9526e6c50dd482625f354cebc64e92b260406024356115c581611567565b6044356115d181611567565b6115d9613677565b845f525f516020615df15f395f51905f5260205261163c835f20916115fd83613ae7565b61161a835465ffffffffffff808260201c169160501c16866141b9565b65ffffffffffff81169261162d84613b3d565b6116378582612ec7565b612eee565b65ffffffffffff8351921682526020820152a2005b346103bc5760203660031901126103bc5761001e600435611670613677565b805f525f516020615df15f395f51905f5260205260405f2061169181613ae7565b805462ff0100600160b01b03191681556116ad60018201613c6d565b805460ff19169055807fd76dbee353f8817df12bf008d3fec1c2f26c9afc1e832f74757756b060b25f825f80a26116e381612afb565b612c25565b346103bc5760203660031901126103bc57600435611705816103ab565b61170d613677565b7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff1086001600160a01b0361173f82614243565b16916001600160a01b038116908184146106cc576117616117819215156136d1565b5f516020615f515f395f51905f5254600160ff1b81166106be5750614bc5565b5f516020615f515f395f51905f52556001600160a01b03906117ad906117a8908190614243565b61039f565b16907f9efc8bb238b1965522b3e784290f41e0229e21a34f499fd2f71b64463283a4165f80a3005b346103bc575f3660031901126103bc5760206040515f516020615db15f395f51905f528152f35b346103bc5760203660031901126103bc576004356001600160401b0381116103bc5761188461184b61183460209336906004016109b9565b61183c612f15565b50838082518301019101612f55565b9461187660409a979a9992959899949394519a8b9a15158b52610120898c01526101208b01906106fe565b9089820360408b01526106fe565b956060880152608087015260a086015260c0850152805160e085015201516101008301520390f35b346103bc575f3660031901126103bc5760206113307f00000000000000000000000000000256d7ef704c043cb352d7d6d3546a720a2e61421a565b346103bc5760403660031901126103bc57600435602435611907816103ab565b61190f613677565b815f525f516020615df15f395f51905f5260205261192f60405f20613ae7565b815f525f516020615eb15f395f51905f5260205260405f206119518282613b5c565b156110d257818161198261196b8360016119879601612c10565b60035f918281558260018201558260028201550155565b614082565b506001600160a01b0316907f6e3ad536abf3a5f8ecec8622b4db221c02989f9d058921928dbc2cf1350924595f80a3005b346103bc575f3660031901126103bc57611a5c6119f47f4f5046373730325265636f76657261626c650000000000000000000000000012615559565b611a1d7f31000000000000000000000000000000000000000000000000000000000000016155d8565b6020604051611a2c8282610945565b5f815281611a6a81830194601f198301368737604051978897600f60f81b895260e0858a015260e08901906106fe565b9087820360408901526106fe565b914660608701523060808701525f60a087015285830360c087015251918281520192915f5b828110611a9e57505050500390f35b835185528695509381019392810192600101611a8f565b346103bc575f3660031901126103bc576040517f00000000000000000000000000000000000000000000000000000000000697806001600160a01b03168152602090f35b346103bc575f3660031901126103bc576040517f000000000000000000000000000000000000000000000000000000000002a3006001600160a01b03168152602090f35b346103bc5760203660031901126103bc57600435611b59613677565b805f525f516020615df15f395f51905f5260205260405f20805460ff8160081c1615611bac5761ff00191690557f04578caed19b0bb078c008c95ca4970e8a3487c04ec67e7748868d2229d2a5675f80a2005b6308bc90d160e41b5f5260045ffd5b346103bc575f3660031901126103bc576040517f00000000000000000000000000000256d7ef704c043cb352d7d6d3546a720a2e6001600160a01b03168152602090f35b346103bc575f3660031901126103bc5760205f516020615db15f395f51905f5254604051908152f35b346103bc575f3660031901126103bc5760206001600160a01b03611c6b7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108614243565b16604051908152f35b346103bc5760603660031901126103bc57600435611c91816103ab565b60443590602435906001600160401b0383116103bc57611ccf5f9392611cbc859436906004016103cd565b9290611cc6613677565b5a933691610983565b9260208451940192f115611cdf57005b611ce7613fda565b602081519101fd5b346103bc5760403660031901126103bc576040611d27600435602435905f525f516020615dd15f395f51905f52602052825f20613e9f565b8151908060601c825263ffffffff60e01b9060e01b166020820152f35b346103bc5760203660031901126103bc576004355f525f516020615dd15f395f51905f52602052602061155f60405f20613e43565b6001600160401b0381116108ef5760051b60200190565b9080601f830112156103bc578135611da781611d79565b92611db56040519485610945565b81845260208085019260051b8201019283116103bc57602001905b828210611ddd5750505090565b8135815260209182019101611dd0565b346103bc5760a03660031901126103bc57611e096004356103ab565b611e146024356103ab565b6044356001600160401b0381116103bc57611e33903690600401611d90565b506064356001600160401b0381116103bc57611e53903690600401611d90565b506084356001600160401b0381116103bc57611e739036906004016109b9565b5060405163bc197c8160e01b8152602090f35b60206040818301928281528451809452019201905f5b818110611ea95750505090565b82516001600160a01b0316845260209384019390920191600101611e9c565b346103bc5760203660031901126103bc576004355f525f516020615eb15f395f51905f52602052611efb60405f20615301565b80549060018060601b038216906040519260601c68fbb67fda52d4bfb8bf811415810284602001528215611f8857509060011c9060015b828110611f605750505b80825260051b810190602082019182604052611f5b601f199284611e86565b030190f35b8060019183015460601c68fbb67fda52d4bfb8bf8114150260208260051b8701015201611f32565b611f93575b50611f3c565b90506001908181015460601c80611fab575b50611f8d565b68fbb67fda52d4bfb8bf81141502604084015260029081015490915060601c80611fd6575b80611fa5565b68fbb67fda52d4bfb8bf8114150260608301525060035f611fd0565b346103bc5760203660031901126103bc57602061201060043561426c565b1515604051908152f35b346103bc575f3660031901126103bc57604460206001600160a01b0361205f7f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108614243565b1660405192838092631aab3f0d60e11b82523060048301525f60248301525afa80156111f457610508915f916120a057506040519081529081906020820190565b6120c2915060203d6020116120c8575b6120ba8183610945565b810190612fe6565b5f610b8b565b503d6120b0565b600711156106f957565b9060078210156106f95752565b346103bc5760403660031901126103bc57608061212a60243560043561210b826103ab565b5f525f516020615eb15f395f51905f52602052600160405f2001612c10565b60ff81541690600181015490600360028201549101549161214e60405180956120d9565b602084015260408301526060820152f35b346103bc5760203660031901126103bc576004356001600160401b0381116103bc5761219261001e9136906004016114f3565b613094565b346103bc5760203660031901126103bc576004355f525f516020615df15f395f51905f52602052602060ff60405f205460081c166040519015158152f35b346103bc5760803660031901126103bc576004356001600160401b0381116103bc576122059036906004016114f3565b6024356001600160401b0381116103bc576122249036906004016114f3565b60443591906001600160401b0383116103bc5761224861001e9336906004016109b9565b9060643592613168565b346103bc5760203660031901126103bc5760043561226f816103ab565b612277613677565b7f00000000000000000000000000000256d7ef704c043cb352d7d6d3546a720a2e6001600160a01b036122a98261421a565b16916001600160a01b038116908184146106cc576122cb6122eb9215156136d1565b5f516020615e515f395f51905f5254600160ff1b81166106be5750614bc5565b5f516020615e515f395f51905f52556001600160a01b039061230c9061421a565b16907f582b29c1adebb6b92690fa23a273813a1d8762da5387e13b24d44a5be6694eb25f80a3005b60206040818301928281528451809452019201905f5b8181106123575750505090565b825184526020938401939092019160010161234a565b346103bc5760203660031901126103bc576004355f525f516020615dd15f395f51905f526020526123a060405f20615312565b8019549060405191826020018115612407575060011c905f5b8281106123e25750505b80825260051b810190602082019182604052611f5b601f199284612334565b8060019183015468fbb67fda52d4bfb8bf8114150260208260051b87010152016123b9565b90918054918261241a575b5050506123c3565b9091925060019268fbb67fda52d4bfb8bf8114150290528181015480612441575b80612412565b68fbb67fda52d4bfb8bf81141502604084015260029081015490915080612469575b8061243b565b68fbb67fda52d4bfb8bf8114150260608301525060035f612463565b61248e36610a2d565b9060025f516020615f115f395f51905f5254146124dd576124c9915f9160025f516020615f115f395f51905f52556124c4613677565b614aa8565b5060015f516020615f115f395f51905f5255005b633ee5aeb560e01b5f5260045ffd5b346103bc5760a03660031901126103bc576125086004356103ab565b6125136024356103ab565b6084356001600160401b0381116103bc576125329036906004016109b9565b5060405163f23a6e6160e01b8152602090f35b801515036103bc57565b346103bc5760803660031901126103bc5760243560043561256f826103ab565b612577610483565b9160643561258481612545565b61258c613677565b825f525f516020615df15f395f51905f526020526125ac60405f20613ae7565b6125b582613b1e565b6001600160a01b0382169330851461279857835f525f516020615dd15f395f51905f5260205260405f20928160e01c9060601b1792825f1461277a57835f946125fd83615312565b9168fbb67fda52d4bfb8bf8114610e94571561276a575b8119918254918160205282156126b2575b805f5260405f209283541561268d575050505050835b612676575b505f516020615e715f395f51905f5292505b604080516001600160e01b0319909216825291151560208201529081908101610d56565b61268261080091613e43565b11610d7c575f612640565b9091929394975060011c8092015560010180915560011b60011790556001928361263b565b91508054801561275d5787838214612753575060018201805490811561274157508884821461273657506002830191825492831561272357508985841461271757505f52600160405f20555f52600260405f20555f52600360405f2055600791612625565b9550505050505061263b565b955050505050919450556001928361263b565b94505050505061263b565b9450505050919450556001928361263b565b935050505061263b565b505550600193508361263b565b5068fbb67fda52d4bfb8bf612614565b5f516020615e715f395f51905f529361279291613ecc565b50612652565b63515ade7d60e11b5f5260045ffd5b346103bc5760403660031901126103bc5760243560043560078210156103bc5760209161155f91613471565b604051906127e0826108d3565b606060e0835f81525f60208201525f60408201525f838201525f60808201525f60a08201525f60c08201520152565b9065ffffffffffff169052565b90600182811c9216801561284a575b602083101461283657565b634e487b7160e01b5f52602260045260245ffd5b91607f169161282b565b5f92918154916128638361281c565b80835292600181169081156128b8575060011461287f57505050565b5f9081526020812093945091925b83831061289e575060209250010190565b60018160209294939454838587010152019101919061288d565b915050602093945060ff929192191683830152151560051b010190565b906103cb6128e99260405193848092612854565b0383610945565b815160208110612929576040811490811561291e575b5015612915576107aa91613944565b6107aa9161377c565b60419150145f612906565b506001600160e01b031992915050565b6020909392919361294e8160408101966120d9565b0152565b600411156103bc57565b51906103cb82611567565b92919261297382610968565b916129816040519384610945565b8294818452818301116103bc578281602093845f96015e010152565b9080601f830112156103bc5781516107aa92602001612967565b600211156103bc57565b51906103cb826129b7565b6020818303126103bc578051906001600160401b0382116103bc570160c0818303126103bc57604051916129ff836108f4565b8151612a0a81612952565b8352612a186020830161295c565b6020840152612a296040830161295c565b6040840152612a3a6060830161295c565b60608401526080820151916001600160401b0383116103bc57612a6460a092612a6f94830161299d565b6080850152016129c1565b60a082015290565b908060209392818452848401375f828201840152601f01601f1916010190565b9035601e19823603018112156103bc570160208101919035906001600160401b0382116103bc5781360383136103bc57565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b6020039060208211612af657565b612ad4565b90612b04613677565b815f525f516020615dd15f395f51905f5260205260405f20915b612b2783613e43565b15612b5957612b3583613e43565b5f198101908111612af657612b4d612b539185613e9f565b84613ecc565b50612b1e565b9091507f4006c450d7cae5e42b4992ac6ffdb9cbdd07a4bfa35a5da3cdf25383ca3ef9555f80a2565b634e487b7160e01b5f52603260045260245ffd5b9190811015612bb85760051b81013590605e19813603018212156103bc570190565b612b82565b356107aa816103ab565b903590601e19813603018212156103bc57018035906001600160401b0382116103bc576020019181360383136103bc57565b6040906107aa9392815281602082015201906106fe565b9060018060a01b03165f5260205260405f2090565b90612c2e613677565b815f525f516020615eb15f395f51905f5260205260405f209060018201925b612c5683614022565b15612ccc57612c6483614022565b5f19810190808211612af6575f1990612c7c86615301565b01015460601c68fbb67fda52d4bfb8bf8114150290612c9a85614022565b1115612cbd5780612cb161196b612cb79388612c10565b84614082565b50612c4d565b634e23d03560e01b5f5260045ffd5b915091507f5ce7f2501695f5fcb7ccc8d0244e32ab2a94fce2349c38a12b5bd275663ec8f05f80a2565b356107aa81612952565b356107aa81611567565b600211156106f957565b356107aa816129b7565b9060028210156106f95752565b9796949160a09465ffffffffffff612d73958180946103cb9b968e612d4f826106ef565b521660208d01521660408b015216606089015260c0608089015260c0880191612a77565b940190612d1e565b939291612dca90612dbc6060937f82dc6262fca76342c646d126714aa4005dfcd866448478747905b2e7b983718388526080602089015260808801906106fe565b9086820360408801526106fe565b930152565b9091612ebf6107aa93612e46612de485612cf6565b612e38612df360208801612d00565b9660a0612e0260408301612d00565b91612e0f60608201612d00565b612e28612e1f6080840184612bc7565b94909301612d14565b936040519b8c9760208901612d2b565b03601f198101865285610945565b612eab612e5282612cf6565b612e9d612e6160208501612d00565b9360a0612e7060408301612d00565b91612e7d60608201612d00565b612e8d612e1f6080840184612bc7565b9360405198899760208901612d2b565b03601f198101835282610945565b612e9d604051938492602084019687612d7b565b519020614193565b805465ffffffffffff60201b191660209290921b65ffffffffffff60201b16919091179055565b805465ffffffffffff60801b191660809290921b65ffffffffffff60801b16919091179055565b60405190612f228261090f565b5f6020838281520152565b91908260409103126103bc57604051612f458161090f565b6020808294805184520151910152565b9190610120838203126103bc578251612f6d81612545565b60208401519093906001600160401b0381116103bc5782612f8f91830161299d565b60408201519093906001600160401b0381116103bc57820183601f820112156103bc5783816020612fc293519101612967565b926060830151926080810151926107aa60a08301519360e060c08501519401612f2d565b908160209103126103bc575190565b35906103cb826129b7565b91909160c0818403126103bc576040519061301a826108f4565b8193813561302781612952565b835261303560208301611577565b602084015261304660408301611577565b604084015261305760608301611577565b60608401526080820135906001600160401b0382116103bc578261308460a0949261308f948694016109b9565b608086015201612ff5565b910152565b61309c613677565b6130ae6130a93683613000565b6142ab565b65ffffffffffff60608201356130c381611567565b16156131595760208101356130d781611567565b65ffffffffffff6040830135916130ed83611567565b1642811191821592613147575b508115613137575b508015613130575b6131215761311c6103cb913690613000565b614429565b6315748a4b60e21b5f5260045ffd5b505f61310a565b65ffffffffffff9150145f613102565b65ffffffffffff16811091505f6130fa565b63710d3ccf60e01b5f5260045ffd5b5f516020615e915f395f51905f525460ff604082901c16159491939192906001600160401b031680159081613270575b6001149081613266575b15908161325d575b5061324e575f516020615e915f395f51905f5280546001600160401b03191660011790556131dc938561322a57613333565b6131e257565b5f516020615e915f395f51905f52805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1565b5f516020615e915f395f51905f52805460ff60401b1916600160401b179055613333565b63f92ee8a960e01b5f5260045ffd5b9050155f6131aa565b303b1591506131a2565b869150613198565b9061328581602093612d1e565b0190565b61332d90604051918183923561329e81612952565b6132a7816106ef565b835265ffffffffffff60208201356132be81611567565b16602084015265ffffffffffff60408201356132d981611567565b16604084015265ffffffffffff60608201356132f481611567565b16606084015261332860a061330c6080840184612a97565b80608088019283375f82820152601f01601f1916019201612ff5565b613278565b03902090565b916112b261336d91613343613677565b61334b6146e5565b61335d6133583687613000565b6147d4565b613368868587612dcf565b6148dc565b6134625761337e61311c3684613000565b61339e6133986133916080840184612bc7565b3691610983565b51151590565b613453575b507f00000000000000000000000000000000000000000000000000000000000697806001600160a01b0316803b156103bc576040516317bb86a960e31b815230600482015260248101939093525f908390604490829084905af19182156111f45761341392613439575b50613289565b7fb5b1af3301534d7bff74b4dc407f8fed41a9b4054c8f61f50229b7c8653cc3545f80a2565b806134475f61344d93610945565b80610ab5565b5f61340d565b61345c90613094565b5f6133a3565b6391cc582560e01b5f5260045ffd5b61347a826120cf565b811561363e57613489826120cf565b600182146136325761349a826120cf565b60028214613625576134ab826120cf565b60038214613603576135359062015180620afa6c91040162023ab1810661016d62023ab082146105b48304618eac8404840103030490606482048260021c8361016d0201039003916001609960028560050201049361030161f4ff6b01820283038404850586008160a11b871a960201600b1c9003019161019062023ab160038610930402010192565b5061353f836120cf565b600483146135b15750613551826120cf565b600582146135745750806135666006926120cf565b1461356f575f80fd5b600190565b6107aa915062015180905f190161013361019082069162023ab1610190620afa6c1994606481049061016d8160021c910201039204020101010290565b906107aa925090620151809160038210900362023ab1610190600181840694620afa6c1995610301600c60096064840494010661f4ff0201600b1c9061016d8160021c91020101030192040201010290565b6107aa91506201518090620545ff828204911190600760038201069003020290565b6201518091508190040290565b610e1091508190040290565b603c91508190040290565b6040513481527fa2a2db73af12c9f5bef6303364d44e78f97e992c353cd8659f3474c471427e9b60203392a2565b3033148015613697575b1561368857565b633b56275760e21b5f5260045ffd5b506001600160a01b036136c97f0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108614243565b163314613681565b156136d857565b633e793d8d60e01b5f5260045ffd5b9060206107aa9281815201906106fe565b908160209103126103bc57516107aa81612545565b96939061012098959b9a99969361374c9361373e928a52151560208a015261014060408a01526101408901906106fe565b9087820360608901526106fe565b98608086015260a085015260c084015260e08301526101008201520152565b908152602081019190915260400190565b905f6137a59261378a612f15565b50604051809481926378daf0d160e01b8352600483016136e7565b0381305afa5f915f915f905f935f935f96835f995f9561390a575b506137db57506001600160e01b031998975050505050505050565b6020956138419193959790989994996138196117a86117a87f00000000000000000000000000000256d7ef704c043cb352d7d6d3546a720a2e61421a565b958b5191898d019b8c51946040519c8d9b8c9a8b9a631e154edd60e21b8c5260048c0161370d565b03915afa5f91816138d9575b5061386257506001600160e01b031992915050565b156138ca576138a06138a59161388b6138af9451915191612e9d6040519384926020840161376b565b6020815191012060015f5260205260405f2090565b610571565b5460101c60ff1690565b6138bf576001600160e01b031990565b630b135d3f60e11b90565b506001600160e01b0319919050565b6138fc91925060203d602011613903575b6138f48183610945565b8101906136f8565b905f61384d565b503d6138ea565b9650985050955050505061393091503d805f833e6139288183610945565b810190612f55565b90989197939692959093909290915f6137c0565b61394d91614c07565b50613957816106ef565b6139d0576001600160a01b03811630146139c457604080516001600160a01b03909216602080840191909152825260ff916139af916138a0919061399b9082610945565b602081519101205f805260205260405f2090565b5460101c166138bf576001600160e01b031990565b50630b135d3f60e11b90565b506001600160e01b031990565b906101008201916139ee8382612bc7565b819391016040848203126103bc57833593613a0885612952565b6020810135906001600160401b0382116103bc57613a3d92613a3592613a2e92016109b9565b9584612bc7565b905084614c41565b613a46836106ef565b8215613aac57613a55836106ef565b60018314613aa057613a66836106ef565b600283148015613a8d575b613a84576322078d5b60e21b5f5260045ffd5b6107aa93615182565b50613a97836106ef565b60038314613a71565b9091506107aa92614f2f565b9091506107aa92614d80565b3d15613ae2573d90613ac982610968565b91613ad76040519384610945565b82523d5f602084013e565b606090565b5460ff8160081c1615613b0f5760101c60ff16613b0057565b632d821d5d60e21b5f5260045ffd5b6311493b1760e31b5f5260045ffd5b6001600160a01b031615613b2e57565b634df8b1b960e11b5f5260045ffd5b1561315957565b9060078110156106f95760ff80198354169116179055565b613b6590615301565b6001600160a01b039091169068fbb67fda52d4bfb8bf8214610e94578115613bda575b80546001600160601b03811615613ba957506020525f5260405f2054151590565b91908160019360601c14613bd557818382015460601c14613bd5576002015460601c146107aa57505f90565b505090565b68fbb67fda52d4bfb8bf9150613b88565b613bf490615312565b68fbb67fda52d4bfb8bf8214610e94578115613c46575b80195415613c22576020525f5260405f2054151590565b9060019181815414613bd557818382015414613bd55760020154146107aa57505f90565b68fbb67fda52d4bfb8bf9150613c0b565b818110613c62575050565b5f8155600101613c57565b613c77815461281c565b9081613c81575050565b81601f5f9311600114613c92575055565b81835260208320613cae91601f0160051c810190600101613c57565b808252602082209081548360011b9084198560031b1c191617905555565b613cd46127d3565b505f516020615f315f395f51905f52545f8181525f516020615df15f395f51905f52602052604090819020905190613d1290600190610807846108d3565b60e0820152505f525f516020615df15f395f51905f52602052613d3d600160405f205f815501613c6d565b5f8080525f516020615e315f395f51905f526020525f516020615f315f395f51905f5255565b613d6c816147d4565b7f281b57cfca503b24a53946c6a7ace6730eb4cf9efb5cb77b9f025f7ac0fa3c745f80a1613d9981615323565b9060a081015160028110156106f957825f516020615ed15f395f51905f5260a08451613dc4816106ef565b60405190613dd1816106ef565b8152600160208201525f604082015265ffffffffffff60608201525f6080820152a3613dfc82610571565b805460081c60ff16613e34575f80525f516020615e315f395f51905f526020526103cb925f516020615f315f395f51905f525561533d565b636f2d7e8d60e01b5f5260045ffd5b613e4c90615312565b90811954918260011c921515908054156002600183015415920154159215613e7357505050565b90919293505f90613e995750600190613e9457506002906107aa5750600390565b919050565b92915050565b9190613ec481613eae85615312565b015468fbb67fda52d4bfb8bf8114150293613e43565b1115612cbd57565b9190613ed85f93615312565b9068fbb67fda52d4bfb8bf8114610e94578015613fb8575b811980549182159260011c935f19850191600183811b1794613f5f57816020525f5260405f20948554928315613f56575f8098995019840103613f38575b5050505555600190565b810186199081015491830101819055855260408520555f8080613f2e565b50505050505050565b9450955050505060019281815414613fa25783810182815414613f93575060020190815414613f8e57505f9150565b5f9055565b905f9250600201908154905555565b5f91506002848201918254815501908154905555565b5068fbb67fda52d4bfb8bf613ef0565b925f939184939260208451940192f190565b3d604051906020818301016040528082525f602083013e90565b5f516020615f715f395f51905f525490600160ff1b82161561401d57506001600160a01b031690565b905090565b61402b90615301565b80546001808301546002909301549082901c60016001605f1b03169392901591901590606081901c156001600160601b039091161715614069575050565b90919250600190613e9457506002906107aa5750600390565b91909161408f5f91615301565b6001600160a01b039093169268fbb67fda52d4bfb8bf8414610e94578315614182575b80545f19600182811c60016001605f1b03169182019081901b969094926001600160601b0381161561414d5750836020525f5260405f209384549283156141445750915f959691600193871983010361411c575b5050818060601b03198354161717905555600190565b86199085010154838060601b031981168719838701015560601c865260408620555f80614106565b96505050505050565b9650935050508160019460601c14613fa25783810182815460601c14613f93575060020190815460601c14613f8e57505f9150565b68fbb67fda52d4bfb8bf93506140b2565b60429061419e61543d565b906040519161190160f01b8352600283015260228201522090565b65ffffffffffff1665ffffffffffff428211931681111591831593614208575b5082156141f8575b5081156141f0575b5061312157565b90505f6141e9565b65ffffffffffff1491505f6141e1565b65ffffffffffff16811092505f6141d9565b5f516020615e515f395f51905f525490600160ff1b82161561401d57506001600160a01b031690565b5f516020615f515f395f51905f525490600160ff1b82161561401d57506001600160a01b031690565b9069ffff00000000ffffffff5f9260b01c16690100000000007821000281146142a2575b600160481b1461429c57565b60019150565b60039250614290565b6080015151156142b757565b638b0cdba160e01b5f5260045ffd5b906142d0816106ef565b60ff80198354169116179055565b9190601f81116142ed57505050565b6103cb925f5260205f20906020601f840160051c83019310614317575b601f0160051c0190613c57565b909150819061430a565b81519192916001600160401b0381116108ef5761434881614342845461281c565b846142de565b6020601f82116001146143875781906143789394955f9261437c575b50508160011b915f199060031b1c19161790565b9055565b015190505f80614364565b601f1982169061439a845f5260205f2090565b915f5b8181106143d4575095836001959697106143bc575b505050811b019055565b01515f1960f88460031b161c191690555f80806143b2565b9192602060018192868b01518155019401920161439d565b9365ffffffffffff92908360809581939998949960a089019a61440e816106ef565b89521515602089015216604087015216606085015216910152565b61443281615323565b61443b81610571565b805460081c60ff16613e345761445b8351614455816106ef565b826142c6565b61446c608084015160018301614321565b602083019061448a614484835165ffffffffffff1690565b82612ec7565b60408401906144c66144a2835165ffffffffffff1690565b825465ffffffffffff60501b191660509190911b65ffffffffffff60501b16178255565b6060850161450665ffffffffffff6144e4835165ffffffffffff1690565b6144ee8186612eee565b845462ff0000191691161560101b62ff000016178355565b815463ff00ff00191661010017825560a08601805160019061452781612d0a565b61453081612d0a565b14614608575b93614603916145ed6145e06145d36145c65f516020615ed15f395f51905f52998b6145835f516020615db15f395f51905f52545f525f516020615e315f395f51905f5260205260405f2090565b556145b061459f5f516020615db15f395f51905f525460010190565b5f516020615db15f395f51905f5255565b519b6145bb8d612d0a565b51976138a5896106ef565b975165ffffffffffff1690565b935165ffffffffffff1690565b915165ffffffffffff1690565b916145f789612d0a565b604051958695866143ec565b0390a3565b825463ff000000191663010000001783559381516001600160a01b037f000000000000000000000000000000000000000000000000000000000002a3001692906146609065ffffffffffff165b65ffffffffffff1690565b92803b156103bc57604051634698642560e01b81523060048201526024810189905260448101949094525f908490606490829084905af180156111f4576145e06145d36145c65f516020615ed15f395f51905f5299614603976145ed956146d1575b50959950505050509150614536565b806134475f6146df93610945565b5f6146c2565b5f6005604051602081017ff3acd96a9d0e27e4323229f52dd3234ce23fb8133871d002e7cbb32c4a47a5c3815260208252614721604083610945565b60ff199151902016828155825f516020615f515f395f51905f5255825f516020615e515f395f51905f5255825f516020615f715f395f51905f52550155565b6107aa90602081528251614773816106ef565b602082015265ffffffffffff602084015116604082015265ffffffffffff604084015116606082015265ffffffffffff606084015116608082015260c060a06147c96080860151838386015260e08501906106fe565b940151910190612d1e565b6147dd816142ab565b65ffffffffffff6147f7606083015165ffffffffffff1690565b16158015906148be575b801561489a575b801561487b575b801561485e575b8015614841575b6148245750565b604051635589ba1160e01b81529081906112f19060048301614760565b506003815161484f816106ef565b614858816106ef565b1461481d565b506002815161486c816106ef565b614875816106ef565b14614816565b5060a081015161488a81612d0a565b61489381612d0a565b151561480f565b5065ffffffffffff806148b6602084015165ffffffffffff1690565b161415614808565b506148d5614655604083015165ffffffffffff1690565b1515614801565b6148f2916148e991614c07565b90929192615847565b6001600160a01b0316301490565b6020818303126103bc578051906001600160401b0382116103bc57019080601f830112156103bc57815161493381611d79565b926149416040519485610945565b81845260208085019260051b820101918383116103bc5760208201905b83821061496d57505050505090565b81516001600160401b0381116103bc5760209161498f8784809488010161299d565b81520191019061495e565b8051821015612bb85760209160051b010190565b6020818303126103bc578051906001600160401b0382116103bc57019080601f830112156103bc578151916149e283611d79565b926149f06040519485610945565b80845260208085019160051b830101918383116103bc5760208101915b838310614a1c57505050505090565b82516001600160401b0381116103bc578201906060828703601f1901126103bc5760405190614a4a8261092a565b6020830151614a58816103ab565b8252604083015160208301526060830151916001600160401b0383116103bc57614a8a8860208096958196010161299d565b6040820152815201920191614a0d565b5f198114612af65760010190565b614ab19061426c565b60038114614b6f5715614b605780602080614ad1935183010191016149ae565b614adb815161563b565b5f915b8151831015614b5a57614b2990614b24614af8858561499a565b51614b03815161039f565b614b0c8161039f565b614b54575030905b6040602082015191015191615666565b614a9a565b91600a8311614b3b5760010191614ade565b6317867ca360e11b5f526004839052600a60245260445ffd5b90614b14565b91505090565b630e5f829b60e01b5f5260045ffd5b50614b88600160f81b9160208082518301019101614900565b614b92815161563b565b5f925b8151841015614bbe57614bb390614bac858461499a565b5184614aa8565b600190930192614b95565b9250505090565b8060a01c614bd657600160ff1b1790565b63714dea2160e11b5f5260045ffd5b9060ff90614bf2836106ef565b6020815191012091165f5260205260405f2090565b8151919060418303614c3757614c309250602082015190606060408401519301515f1a9061568f565b9192909190565b50505f9160029190565b614c4a816106ef565b80614c68575060c010614c5957565b636f60705160e01b5f5260045ffd5b614c71816106ef565b60028114908115614c8e575b50614c855750565b60e010614c5957565b60039150614c9b816106ef565b145f614c7d565b6107aa9291815260406020820152614ccd60408201614cc0846103c0565b6001600160a01b03169052565b60208201356060820152614d6d614d61614d22614d03614cf06040870187612a97565b6101206080880152610160870191612a77565b614d106060870187612a97565b868303603f190160a088015290612a77565b608085013560c085015260a085013560e085015260c0850135610100850152614d4e60e0860186612a97565b858303603f190161012087015290612a77565b92610100810190612a97565b91610140603f1982860301910152612a77565b614d899161562e565b6001600160a01b0381163014614f2957604080516001600160a01b039092166020830152614dbf919061399b9082908101612e9d565b614dc881610571565b91614dd283615707565b83549092601082901c60ff1680614f22575b614f19575f9185919060181c60ff16614e87575b50614e0b836060614e1194950190612bc7565b90615757565b9182614e7f575b5081614e76575b50614e2a5750600190565b6107aa9054614e53614e448260201c65ffffffffffff1690565b9160501c65ffffffffffff1690565b9060a01b65ffffffffffff60a01b1660d09190911b6001600160d01b0319161790565b9050155f614e1f565b91505f614e18565b604051633894f6e760e11b815292506020915082908190614ead90869060048401614ca2565b03815f7f000000000000000000000000000000000000000000000000000000000002a3006001600160a01b03165af180156111f457614e0b8591614e11935f91614efa575b509250614df8565b614f13915060203d6020116120c8576120ba8183610945565b5f614ef2565b50505050505f90565b5083614de4565b50505f90565b919091805181016020019060200190614f4791612f55565b9593909498916101008998949801614f5f908a612bc7565b86518c51614f6e9350916157a3565b614f977f00000000000000000000000000000256d7ef704c043cb352d7d6d3546a720a2e61421a565b614fa09061039f565b614fa99061039f565b9587519160208901998a51946040519d8e998a99631e154edd60e21b8b5260048b0199614fd59a61370d565b03815a93602094fa9384156111f4575f94615137575b509061388b61500a9251915191612e9d6040519384926020840161376b565b9061501482610571565b9261501e84615707565b928454926150308460ff9060101c1690565b80615130575b80615129575b61511f575f9386929060181c60ff165b61508a575b5090614e0b826060615064940190612bc7565b9283615082575b5082614e7f575081614e765750614e2a5750600190565b92505f61506b565b8194506150b19250906020916040519384928392633894f6e760e11b845260048401614ca2565b03815f7f000000000000000000000000000000000000000000000000000000000002a3006001600160a01b03165af180156111f457614e0b8691615064935f91615100575b5094919250615051565b615119915060203d6020116120c8576120ba8183610945565b5f6150f6565b5050505050505f90565b508261503c565b5084615036565b61500a9291945061515961388b9160203d602011613903576138f48183610945565b94919250614feb565b90916080828403126103bc576107aa825193604060208501519401612f2d565b9061519860209492858082518301019101615162565b93919590926151a6836106ef565b600383036152fb576151b79061582f565b925b6151e86117a86117a87f00000000000000000000000000000256d7ef704c043cb352d7d6d3546a720a2e61421a565b8551838701805160405163028ba33d60e61b81526004810198909852602488019a909a526044870193909352606486015260848501979097529295869060a49082905afa9485156111f4575f956152da575b50615244816106ef565b6002036152a35761526861527d9251915191612e9d6040519384926020840161376b565b6020815191012060025f5260205260405f2090565b61528681610571565b928361529181615707565b935f9361504c835460ff9060181c1690565b6152c06152d59251915191612e9d6040519384926020840161376b565b6020815191012060035f5260205260405f2090565b61527d565b6152f491955060203d602011613903576138f48183610945565b935f61523a565b926151b9565b63978aab926004525f5260245f2090565b6318fb58646004525f5260245f2090565b6107aa906080815191615335836106ef565b015190614be5565b91906080906153568151615350816106ef565b856142c6565b0151805190929060018201906001600160401b0381116108ef5761537e81614342845461281c565b6020601f82116001146153d05790806153b0926103cb96975f9261437c5750508160011b915f199060031b1c19161790565b90555b8054610100600160b01b03191669ffffffffffff00010100179055565b601f198216956153e3845f5260205f2090565b965f5b8181106154255750916103cb96979184600195941061540d575b505050811b0190556153b3565b01515f1960f88460031b161c191690555f8080615400565b838301518955600190980197602093840193016153e6565b307f0000000000000000000000007702080183ee36ef64f317815185d89bfc6b239a6001600160a01b03161480615530575b15615498577f1bf68710e1b88dea173bdc08b16234b75fe31731525d1342575dda1eceadc68990565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f602f321984dba2e0cae87be8f27ab230e276cecfc5935e203cc6621f925ce5c660408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815261552a60c082610945565b51902090565b507f0000000000000000000000000000000000000000000000000000000000aa37dc461461546f565b60ff811461559f5760ff811690601f8211615590576040519161557d604084610945565b6020808452838101919036833783525290565b632cd44ac360e21b5f5260045ffd5b506040516107aa816155d1817feddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad95407612854565b0382610945565b60ff81146155fc5760ff811690601f8211615590576040519161557d604084610945565b506040516107aa816155d1817feddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad95408612854565b6107aa916148e991614c07565b801590811561565b575b5061564c57565b630ea2989360e11b5f5260045ffd5b600a9150115f615645565b915f928392602083519301915af19061567d613ab8565b9161568b5750602081519101fd5b9050565b91906fa2a8918ca85bafe22016d0b997e4df60600160ff1b0384116156fc579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156111f4575f516001600160a01b038116156156f257905f905f90565b505f906001905f90565b5050505f9160039190565b5465ffffffffffff8160201c161515908161572c575b501561572857600190565b5f90565b60ff915060081c165f61571d565b90929192836004116103bc5783116103bc57600401916003190190565b816004116103bc5780356001600160e01b03191663e9ae5c5360e01b1461577f575050505f90565b6107aa926158c3565b9060208201809211612af657565b91908201809211612af657565b9190601f81168061580757506157e7916157d66157db6157e093925b601f8116806157ee5750925b6157d6610120615788565b615796565b615788565b6060615796565b03614c5957565b906157fb61580192612ae8565b90615796565b926157cb565b60200360208111612af6578101809111612af6576157e7916157d66157db6157e093926157bf565b5f5260206001815f60025afa51903d1561584557565bfe5b615850816106ef565b80615859575050565b615862816106ef565b600181036158795763f645eedf60e01b5f5260045ffd5b615882816106ef565b6002810361589d575063fce698f760e01b5f5260045260245ffd5b806158a96003926106ef565b146158b15750565b6335e2f38360e21b5f5260045260245ffd5b91806158d2916158da9361573a565b810190610a5c565b90600160f81b811461597f576880000000003c10800160b11b146158fe5750505f90565b8060208061591193518301019101614900565b905f915b80518310156159775761593b61592b848361499a565b51602080825183010191016149ae565b905f5b825181101561596a5761595e6112b2615957838661499a565b51866159c9565b614f195760010161593e565b5092600191500191615915565b505050600190565b5080602080615993935183010191016149ae565b905f5b8251811015615977576159b66112b26159af838661499a565b51846159c9565b6159c257600101615996565b5050505f90565b906159d4815161039f565b6001600160a01b03163014614f29576159ef6112b283615ac7565b614f2957615a13615a01835460ff1690565b615a0d600185016128d5565b90614be5565b90615a1e815161039f565b90615a336112b2604083019384519086615aec565b615abf5760208101805190919015615aad57615a6c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b615a678661058b565b613b5c565b615a7e575b5050505061356f90615cd7565b91615a9b9391615a916112b2945161039f565b9051915192615bf9565b615aa8575f808080615a71565b505f90565b615a6c615aba825161039f565b615a5e565b505050505f90565b5460ff8160101c16908115615ada575090565b65ffffffffffff915060801c16151590565b82519192631919191960e11b92906004821015615bed575b5015615bde575b615b29905f525f516020615dd15f395f51905f5260205260405f2090565b91615b3383613e43565b615b3e575050505f90565b615b52606082901b60e084901c1784613beb565b61597757615b699060601b63323232321783613beb565b615bd757615b93615b999160e01c73191919191919191919191919191919191919191960611b1790565b82613beb565b615bd157615bc590633232323273191919191919191919191919191919191919191960611b0190613beb565b61356f575f80806159c2565b50600190565b5050600190565b630707070760e51b9150615b0b565b6020015192505f615b04565b90916112b292615c5794631919191960e11b81516004811015615ccb575b15615cbd575b5f906001600160e01b031916630707070760e51b8103615c6057505050509073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90615d1f565b61572857600190565b929350909163a9059cbb60e01b8103615c7f5750506044015191615d1f565b6323b872dd60e01b8103615c995750506064015191615d1f565b9093919063095ea7b360e01b14615cb1575b50615d1f565b6044015192505f615cab565b50630707070760e51b615c1d565b60208301519150615c17565b80549060ff8260101c161580615d0b575b615cf0575050565b6103cb9160801c65ffffffffffff9081165f19011690612eee565b5065ffffffffffff8260801c161515615ce8565b906001615d2e615d349361058b565b01612c10565b90615d40825460ff1690565b615d49816120cf565b60ff8116158015615da4575b6159c257615d639042613471565b6003830181815410615d96575b505060028201918254906001615d868484615796565b910154106159c257019055600190565b555f60028301555f80615d70565b50600183015415615d5556feeddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad95400eddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad95403eddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad95402360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbceddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad95401fd39baddba6b1a9197cb18b09396db32f340e9b468af2bcc8f997735c03db200a689a7e36dc35eca77c11a22d2ca34732d3c60bf0c123ad7961c8172b68232e6eddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad95406eddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad954049a25b188db17eecf356ac506ac927ec7685bb79ce1d73d874b5ccf8a1e7deaa4ccaf96466f328cb6c7abea8b5cbcd657935ce852f154955ff06dd44646ca739ceddd36aac8c71936fe1d5edb073ff947aa7c1b6174e87c15677c96ab9ad9540560d0e7bd51fec56c7958fb69ada2df2c0622337648a8c42d14584aac9f26a1014e696bb2fc09e5383cb7d4063d5fb8f6e0701a72d9523e5f996ae73b7c89e800da9fe820be906bb4b68c951302595f7e1131563db95582cda480475cc85e6800a26469706673582212203c95b8b15fb4f6fd89ea67554089d4496ab1a5d85973095978eeaca50227c1f064736f6c634300081d0033" + ); } function _uniswapV2SwapPayload() internal view returns (bytes memory) { @@ -241,9 +266,343 @@ contract BenchmarkTest is BaseTest { SafeTransferLib.safeApprove( address(paymentToken), _PIMLICO_PAYMASTER_V07, type(uint128).max ); + SafeTransferLib.safeApprove( + address(paymentToken), _PIMLICO_PAYMASTER_V08, type(uint128).max + ); vm.stopPrank(); } + /** + * Tests for the OPF7702 account with EPv8 + */ + function _createOPF7702Account(uint256 numAccounts) + internal + returns (address[] memory eoas, uint256[] memory privateKeys) + { + eoas = new address[](numAccounts); + privateKeys = new uint256[](numAccounts); + + for (uint256 i = 0; i < numAccounts; i++) { + (eoas[i], privateKeys[i]) = makeAddrAndKey(string(abi.encodePacked("opf7702", i))); + vm.etch(eoas[i], abi.encodePacked(hex"ef0100", address(_OPF7702))); + _giveAccountSomeTokens(eoas[i]); + } + } + + function testNativeTransfer_Openfort() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + calls[0] = ERC7821.Call({ + to: address(0xbabe), + value: 1 ether, + data: "" + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(1); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.SELF_ETH + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testNativeTransfer_Openfort"); + + assertEq(address(0xbabe).balance, 1 ether); + } + + function testERC20Transfer_Openfort() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + + bytes memory transferCallData = abi.encodeWithSignature("transfer(address,uint256)", address(0xbabe), 1 ether); + calls[0] = ERC7821.Call({ + to: address(paymentToken), + value: 0 ether, + data: transferCallData + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(1); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.SELF_ETH + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testERC20Transfer_Openfort"); + + assertEq(paymentToken.balanceOf(address(0xbabe)), 1 ether); + } + + function testERC20Transfer_Openfort_ERC20SelfPay() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + + bytes memory transferCallData = abi.encodeWithSignature("transfer(address,uint256)", address(0xbabe), 1 ether); + calls[0] = ERC7821.Call({ + to: address(paymentToken), + value: 0 ether, + data: transferCallData + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(1); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.SELF_ERC20 + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testERC20Transfer_Openfort_ERC20SelfPay"); + + assertEq(paymentToken.balanceOf(address(0xbabe)), 1 ether); + } + + function testERC20Transfer_Openfort_AppSponsor() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + + bytes memory transferCallData = abi.encodeWithSignature("transfer(address,uint256)", address(0xbabe), 1 ether); + calls[0] = ERC7821.Call({ + to: address(paymentToken), + value: 0 ether, + data: transferCallData + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(1); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.APP_SPONSOR + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testERC20Transfer_Openfort_AppSponsor"); + + assertEq(paymentToken.balanceOf(address(0xbabe)), 1 ether); + } + + function testERC20Transfer_Batch100_Openfort() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + + bytes memory transferCallData = abi.encodeWithSignature("transfer(address,uint256)", address(0xbabe), 1 ether); + calls[0] = ERC7821.Call({ + to: address(paymentToken), + value: 0 ether, + data: transferCallData + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(100); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.SELF_ETH + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testERC20Transfer_Batch100_Openfort"); + + assertEq(paymentToken.balanceOf(address(0xbabe)), 100 ether); + } + + function testERC20Transfer_Batch100_Openfort_ERC20SelfPay() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + + bytes memory transferCallData = abi.encodeWithSignature("transfer(address,uint256)", address(0xbabe), 1 ether); + calls[0] = ERC7821.Call({ + to: address(paymentToken), + value: 0 ether, + data: transferCallData + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(100); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.SELF_ERC20 + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testERC20Transfer_Batch100_Openfort_ERC20SelfPay"); + + assertEq(paymentToken.balanceOf(address(0xbabe)), 100 ether); + } + + function testERC20Transfer_Batch100_Openfort_AppSponsor() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + + bytes memory transferCallData = abi.encodeWithSignature("transfer(address,uint256)", address(0xbabe), 1 ether); + calls[0] = ERC7821.Call({ + to: address(paymentToken), + value: 0 ether, + data: transferCallData + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(100); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.APP_SPONSOR + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testERC20Transfer_Batch100_Openfort_AppSponsor"); + + assertEq(paymentToken.balanceOf(address(0xbabe)), 100 ether); + } + + function testUniswapV2Swap_Openfort() public { + ERC7821.Call[] memory calls = new ERC7821.Call[](1); + + bytes memory swapCallData = _uniswapV2SwapPayload(); + calls[0] = ERC7821.Call({ + to: _UNISWAP_V2_ROUTER_ADDRESS, + value: 0 ether, + data: swapCallData + }); + + bytes32 mode_1 = bytes32(uint256(0x01000000000000000000) << (22 * 8)); + bytes memory executionData = abi.encode(calls); + + bytes memory payload = abi.encodeWithSelector(bytes4(keccak256("execute(bytes32,bytes)")), mode_1, executionData); + + (address[] memory eoas, uint256[] memory privateKeys) = _createOPF7702Account(1); + + PackedUserOperationV8[] memory u = _getPayload_OPF7702Account( + payload, "", eoas, privateKeys, PaymentType.SELF_ETH + ); + + vm.startPrank(relayer); + erc4337EntryPointV8.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testUniswapV2Swap_Openfort"); + } + + function _getPayload_OPF7702Account( + bytes memory payload, + bytes memory junk, + address[] memory eoas, + uint256[] memory privateKeys, + PaymentType _paymentType + ) internal view returns (PackedUserOperationV8[] memory) { + PackedUserOperationV8[] memory u = new PackedUserOperationV8[](eoas.length); + for (uint256 i = 0; i < eoas.length; i++) { + u[i].sender = address(eoas[i]); + u[i].nonce = erc4337EntryPointV8.getNonce(address(eoas[i]), 0); + u[i].accountGasLimits = bytes32(uint256(1000000 | (1000000 << 128))); + u[i].preVerificationGas = 1000000; + u[i].gasFees = bytes32(uint256(1000000 | (1000000 << 128))); + u[i].callData = abi.encodePacked(payload, junk); /// Todo: add mode_1 for erc7821 + + // Set paymaster based on payment type + if (_paymentType == PaymentType.SELF_ERC20) { + u[i].paymasterAndData = abi.encodePacked( + _PIMLICO_PAYMASTER_V08, + uint128(1000000), // verification gas limit + uint128(1000000), // postOp gas limit + uint8(1) | uint8(1 << 1), // allow all bundlers + erc20 mode + uint8(0), // no prefund, no constant fee, no recipient + type(uint48).max, // max validUntil + uint48(0), // no validAfter + paymentToken, // payment token + uint128(100000), // post op gas + uint256(1e18), // exchange rate + uint128(100000), // paymaster vgl + relayer // treasury + ); + + u[i].paymasterAndData = abi.encodePacked( + u[i].paymasterAndData, + _eoaSig( + paymasterPrivateKey, + SignatureCheckerLib.toEthSignedMessageHash( + PimlicoHelpers.getHashV8(1, u[i]) + ) + ) + ); + } else if (_paymentType == PaymentType.APP_SPONSOR) { + u[i].paymasterAndData = abi.encodePacked( + _PIMLICO_PAYMASTER_V08, + uint128(1000000), // verification gas limit + uint128(1000000), // postOp gas limit + uint8(1), // allow all bundlers + native token mode + type(uint48).max, // max validUntil + uint48(0) // no validAfter + ); + + u[i].paymasterAndData = abi.encodePacked( + u[i].paymasterAndData, + _eoaSig( + paymasterPrivateKey, + SignatureCheckerLib.toEthSignedMessageHash( + PimlicoHelpers.getHashV8(0, u[i]) + ) + ) + ); + } + + bytes memory rawSignature = _eoaSig( + privateKeys[i], + erc4337EntryPointV8.getUserOpHash(u[i]) + ); + + u[i].signature = abi.encode(uint8(0), rawSignature); // EOA signature type + } + + return u; + } + + function testNativeTransfer_OPF7702() public { + bytes memory payload = + abi.encodeWithSignature("execute(address,uint256,bytes)", address(0xbabe), 1 ether, ""); + (address[] memory accounts, address[] memory eoas, uint256[] memory privateKeys) = + _createCoinbaseSmartWallet(1); + + UserOperation[] memory u = _getPayload_CoinbaseSmartWallet( + payload, "", accounts, eoas, privateKeys, PaymentType.SELF_ETH + ); + + vm.startPrank(relayer); + erc4337EntryPointV6.handleOps(u, payable(relayer)); + vm.snapshotGasLastCall("testNativeTransfer_CoinbaseSmartWallet"); + + assertEq(address(0xbabe).balance, 1 ether); + } + /** * Tests for the ERC4337 minimal account */ diff --git a/test/utils/interfaces/IERC4337EntryPointV8.sol b/test/utils/interfaces/IERC4337EntryPointV8.sol new file mode 100644 index 00000000..4212a44d --- /dev/null +++ b/test/utils/interfaces/IERC4337EntryPointV8.sol @@ -0,0 +1,431 @@ +/** + ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. + ** Only one instance required on each chain. + **/ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ +/* solhint-disable reason-string */ + +/** + * User Operation struct + * @param sender - The sender account of this request. + * @param nonce - Unique value the sender uses to verify it is not a replay. + * @param initCode - If set, the account contract will be created by this constructor + * @param callData - The method call to execute on this account. + * @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call. + * @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid. + * Covers batch overhead. + * @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters. + * @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data + * The paymaster will pay for the transaction instead of the sender. + * @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID. + */ +struct PackedUserOperation { + address sender; + uint256 nonce; + bytes initCode; + bytes callData; + bytes32 accountGasLimits; + uint256 preVerificationGas; + bytes32 gasFees; + bytes paymasterAndData; + bytes signature; +} + +/** + * Aggregated Signatures validator. + */ +interface IAggregator { + /** + * Validate an aggregated signature. + * Reverts if the aggregated signature does not match the given list of operations. + * @param userOps - An array of UserOperations to validate the signature for. + * @param signature - The aggregated signature. + */ + function validateSignatures( + PackedUserOperation[] calldata userOps, + bytes calldata signature + ) external; + + /** + * Validate the signature of a single userOp. + * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns + * the aggregator this account uses. + * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. + * @param userOp - The userOperation received from the user. + * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps. + * (usually empty, unless account and aggregator support some kind of "multisig". + */ + function validateUserOpSignature( + PackedUserOperation calldata userOp + ) external view returns (bytes memory sigForUserOp); + + /** + * Aggregate multiple signatures into a single value. + * This method is called off-chain to calculate the signature to pass with handleOps() + * bundler MAY use optimized custom code to perform this aggregation. + * @param userOps - An array of UserOperations to collect the signatures from. + * @return aggregatedSignature - The aggregated signature. + */ + function aggregateSignatures( + PackedUserOperation[] calldata userOps + ) external view returns (bytes memory aggregatedSignature); +} + +interface ISenderCreator { + /** + * @dev Creates a new sender contract. + * @return sender Address of the newly created sender contract. + */ + function createSender(bytes calldata initCode) external returns (address sender); + + /** + * Use initCallData to initialize an EIP-7702 account. + * The caller is the EntryPoint contract and it is already verified to be an EIP-7702 account. + * Note: Can be called multiple times as long as an appropriate initCode is supplied + * + * @param sender - the 'sender' EIP-7702 account to be initialized. + * @param initCallData - the call data to be passed to the sender account call. + */ + function initEip7702Sender(address sender, bytes calldata initCallData) external; +} + +interface INonceManager { + + /** + * Return the next nonce for this sender. + * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) + * But UserOp with different keys can come with arbitrary order. + * + * @param sender the account address + * @param key the high 192 bit of the nonce + * @return nonce a full nonce to pass for next UserOp with this sender. + */ + function getNonce(address sender, uint192 key) + external view returns (uint256 nonce); + + /** + * Manually increment the nonce of the sender. + * This method is exposed just for completeness.. + * Account does NOT need to call it, neither during validation, nor elsewhere, + * as the EntryPoint will update the nonce regardless. + * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future + * UserOperations will not pay extra for the first transaction with a given key. + * + * @param key - the "nonce key" to increment the "nonce sequence" for. + */ + function incrementNonce(uint192 key) external; +} + +interface IStakeManager { + event Deposited(address indexed account, uint256 totalDeposit); + + event Withdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + // Emitted when stake or unstake delay are modified. + event StakeLocked( + address indexed account, + uint256 totalStaked, + uint256 unstakeDelaySec + ); + + // Emitted once a stake is scheduled for withdrawal. + event StakeUnlocked(address indexed account, uint256 withdrawTime); + + event StakeWithdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /** + * @param deposit - The entity's deposit. + * @param staked - True if this entity is staked. + * @param stake - Actual amount of ether staked for this entity. + * @param unstakeDelaySec - Minimum delay to withdraw the stake. + * @param withdrawTime - First block timestamp where 'withdrawStake' will be callable, or zero if already locked. + * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp) + * and the rest fit into a 2nd cell (used during stake/unstake) + * - 112 bit allows for 10^15 eth + * - 48 bit for full timestamp + * - 32 bit allows 150 years for unstake delay + */ + struct DepositInfo { + uint256 deposit; + bool staked; + uint112 stake; + uint32 unstakeDelaySec; + uint48 withdrawTime; + } + + // API struct used by getStakeInfo and simulateValidation. + struct StakeInfo { + uint256 stake; + uint256 unstakeDelaySec; + } + + /** + * Get deposit info. + * @param account - The account to query. + * @return info - Full deposit information of given account. + */ + function getDepositInfo( + address account + ) external view returns (DepositInfo memory info); + + /** + * Get account balance. + * @param account - The account to query. + * @return - The deposit (for gas payment) of the account. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * Add to the deposit of the given account. + * @param account - The account to add to. + */ + function depositTo(address account) external payable; + + /** + * Add to the account's stake - amount and delay + * any pending unstake is first cancelled. + * @param unstakeDelaySec - The new lock duration before the deposit can be withdrawn. + */ + function addStake(uint32 unstakeDelaySec) external payable; + + /** + * Attempt to unlock the stake. + * The value can be withdrawn (using withdrawStake) after the unstake delay. + */ + function unlockStake() external; + + /** + * Withdraw from the (unlocked) stake. + * Must first call unlockStake and wait for the unstakeDelay to pass. + * @param withdrawAddress - The address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external; + + /** + * Withdraw from the deposit. + * @param withdrawAddress - The address to send withdrawn value. + * @param withdrawAmount - The amount to withdraw. + */ + function withdrawTo( + address payable withdrawAddress, + uint256 withdrawAmount + ) external; +} + +interface IEntryPoint is IStakeManager, INonceManager { + /*** + * An event emitted after each successful request. + * @param userOpHash - Unique identifier for the request (hash its entire content, except signature). + * @param sender - The account that generates this request. + * @param paymaster - If non-null, the paymaster that pays for this request. + * @param nonce - The nonce value from the request. + * @param success - True if the sender transaction succeeded, false if reverted. + * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation. + * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation, + * validation and execution). + */ + event UserOperationEvent( + bytes32 indexed userOpHash, + address indexed sender, + address indexed paymaster, + uint256 nonce, + bool success, + uint256 actualGasCost, + uint256 actualGasUsed + ); + + /** + * Account "sender" was deployed. + * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow. + * @param sender - The account that is deployed + * @param factory - The factory used to deploy this account (in the initCode) + * @param paymaster - The paymaster used by this UserOp + */ + event AccountDeployed( + bytes32 indexed userOpHash, + address indexed sender, + address factory, + address paymaster + ); + + /** + * An event emitted if the UserOperation "callData" reverted with non-zero length. + * @param userOpHash - The request unique identifier. + * @param sender - The sender of this request. + * @param nonce - The nonce used in the request. + * @param revertReason - The return bytes from the reverted "callData" call. + */ + event UserOperationRevertReason( + bytes32 indexed userOpHash, + address indexed sender, + uint256 nonce, + bytes revertReason + ); + + /** + * An event emitted if the UserOperation Paymaster's "postOp" call reverted with non-zero length. + * @param userOpHash - The request unique identifier. + * @param sender - The sender of this request. + * @param nonce - The nonce used in the request. + * @param revertReason - The return bytes from the reverted call to "postOp". + */ + event PostOpRevertReason( + bytes32 indexed userOpHash, + address indexed sender, + uint256 nonce, + bytes revertReason + ); + + /** + * UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made. + * @param userOpHash - The request unique identifier. + * @param sender - The sender of this request. + * @param nonce - The nonce used in the request. + */ + event UserOperationPrefundTooLow( + bytes32 indexed userOpHash, + address indexed sender, + uint256 nonce + ); + + /** + * An event emitted by handleOps() and handleAggregatedOps(), before starting the execution loop. + * Any event emitted before this event, is part of the validation. + */ + event BeforeExecution(); + + /** + * Signature aggregator used by the following UserOperationEvents within this bundle. + * @param aggregator - The aggregator used for the following UserOperationEvents. + */ + event SignatureAggregatorChanged(address indexed aggregator); + + /** + * A custom revert error of handleOps andhandleAggregatedOps, to identify the offending op. + * Should be caught in off-chain handleOps/handleAggregatedOps simulation and not happen on-chain. + * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. + * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it. + * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero). + * @param reason - Revert reason. The string starts with a unique code "AAmn", + * where "m" is "1" for factory, "2" for account and "3" for paymaster issues, + * so a failure can be attributed to the correct entity. + */ + error FailedOp(uint256 opIndex, string reason); + + /** + * A custom revert error of handleOps and handleAggregatedOps, to report a revert by account or paymaster. + * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero). + * @param reason - Revert reason. see FailedOp(uint256,string), above + * @param inner - data from inner cought revert reason + * @dev note that inner is truncated to 2048 bytes + */ + error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner); + + error PostOpReverted(bytes returnData); + + /** + * Error case when a signature aggregator fails to verify the aggregated signature it had created. + * @param aggregator The aggregator that failed to verify the signature + */ + error SignatureValidationFailed(address aggregator); + + // Return value of getSenderAddress. + error SenderAddressResult(address sender); + + // UserOps handled, per aggregator. + struct UserOpsPerAggregator { + PackedUserOperation[] userOps; + // Aggregator address + IAggregator aggregator; + // Aggregated signature + bytes signature; + } + + /** + * Execute a batch of UserOperations. + * No signature aggregator is used. + * If any account requires an aggregator (that is, it returned an aggregator when + * performing simulateValidation), then handleAggregatedOps() must be used instead. + * @param ops - The operations to execute. + * @param beneficiary - The address to receive the fees. + */ + function handleOps( + PackedUserOperation[] calldata ops, + address payable beneficiary + ) external; + + /** + * Execute a batch of UserOperation with Aggregators + * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts). + * @param beneficiary - The address to receive the fees. + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) external; + + /** + * Generate a request Id - unique identifier for this request. + * The request ID is a hash over the content of the userOp (except the signature), entrypoint address, chainId and (optionally) 7702 delegate address + * @param userOp - The user operation to generate the request ID for. + * @return hash the hash of this UserOperation + */ + function getUserOpHash( + PackedUserOperation calldata userOp + ) external view returns (bytes32); + + /** + * Gas and return values during simulation. + * @param preOpGas - The gas used for validation (including preValidationGas) + * @param prefund - The required prefund for this operation + * @param accountValidationData - returned validationData from account. + * @param paymasterValidationData - return validationData from paymaster. + * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp) + */ + struct ReturnInfo { + uint256 preOpGas; + uint256 prefund; + uint256 accountValidationData; + uint256 paymasterValidationData; + bytes paymasterContext; + } + + /** + * Get counterfactual sender address. + * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. + * This method always revert, and returns the address in SenderAddressResult error. + * @notice this method cannot be used for EIP-7702 derived contracts. + * + * @param initCode - The constructor code to be passed into the UserOperation. + */ + function getSenderAddress(bytes memory initCode) external; + + error DelegateAndRevert(bool success, bytes ret); + + /** + * Helper method for dry-run testing. + * @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result. + * The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace + * actual EntryPoint code is less convenient. + * @param target a target contract to make a delegatecall from entrypoint + * @param data data to pass to target in a delegatecall + */ + function delegateAndRevert(address target, bytes calldata data) external; + + /** + * @notice Retrieves the immutable SenderCreator contract which is responsible for deployment of sender contracts. + */ + function senderCreator() external view returns (ISenderCreator); +} diff --git a/test/utils/interfaces/IPimlicoPaymaster.sol b/test/utils/interfaces/IPimlicoPaymaster.sol index 2665aedc..69e6e2bb 100644 --- a/test/utils/interfaces/IPimlicoPaymaster.sol +++ b/test/utils/interfaces/IPimlicoPaymaster.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.4; import "./IERC4337EntryPoint.sol"; +import {PackedUserOperation as PackedUserOperationV8} from "test/utils/interfaces/IERC4337EntryPointV8.sol"; interface IPimlicoPaymaster { function tokenOracle() external view returns (address); @@ -67,6 +68,45 @@ library PimlicoHelpers { } } + function getHashV8(uint8 _mode, PackedUserOperationV8 calldata _userOp) + public + view + returns (bytes32) + { + if (_mode == VERIFYING_MODE) { + return _getHashV8( + _userOp, MODE_AND_ALLOW_ALL_BUNDLERS_LENGTH + VERIFYING_PAYMASTER_DATA_LENGTH + ); + } else { + uint8 paymasterDataLength = + MODE_AND_ALLOW_ALL_BUNDLERS_LENGTH + ERC20_PAYMASTER_DATA_LENGTH; + + uint8 combinedByte = uint8( + _userOp.paymasterAndData[PAYMASTER_DATA_OFFSET + MODE_AND_ALLOW_ALL_BUNDLERS_LENGTH] + ); + // constantFeePresent is in the *lowest* bit + bool constantFeePresent = (combinedByte & 0x01) != 0; + // recipientPresent is in the second lowest bit + bool recipientPresent = (combinedByte & 0x02) != 0; + // preFundPresent is in the third lowest bit + bool preFundPresent = (combinedByte & 0x04) != 0; + + if (preFundPresent) { + paymasterDataLength += 16; + } + + if (constantFeePresent) { + paymasterDataLength += 16; + } + + if (recipientPresent) { + paymasterDataLength += 20; + } + + return _getHashV8(_userOp, paymasterDataLength); + } + } + function _getHashV7(PackedUserOperation calldata _userOp, uint256 paymasterDataLength) internal view @@ -89,6 +129,28 @@ library PimlicoHelpers { return keccak256(abi.encode(userOpHash, block.chainid)); } + function _getHashV8(PackedUserOperationV8 calldata _userOp, uint256 paymasterDataLength) + internal + view + returns (bytes32) + { + bytes32 userOpHash = keccak256( + abi.encode( + _userOp.sender, + _userOp.nonce, + _userOp.accountGasLimits, + _userOp.preVerificationGas, + _userOp.gasFees, + keccak256(_userOp.initCode), + keccak256(_userOp.callData), + // hashing over all paymaster fields besides signature + keccak256(_userOp.paymasterAndData[:PAYMASTER_DATA_OFFSET + paymasterDataLength]) + ) + ); + + return keccak256(abi.encode(userOpHash, block.chainid)); + } + function getHashV6(uint8 _mode, UserOperation calldata _userOp) public view returns (bytes32) { if (_mode == VERIFYING_MODE) { return _getHashV6(