ETH Price: $1,982.97 (-2.97%)

Transaction Decoder

Block:
14959992 at Jun-14-2022 05:04:54 AM +UTC
Transaction Fee:
0.052784350550757951 ETH $104.67
Gas Used:
1,237,773 Gas / 42.644612987 Gwei

Emitted Events:

458 TransparentUpgradeableProxy.0x10e0571aafaf282151fd5b0215b5495521c549509cb0de3a3f8310bd2e344682( 0x10e0571aafaf282151fd5b0215b5495521c549509cb0de3a3f8310bd2e344682, 0x0000000000000000000000000000000000000000000000000000000001cca597, 0x8ddeb11cf7851a4e2041fecc9b40126eac955e4654c9b532be48b1690659b828, 0000000000000000000000000000000000000000000000000000000001cca6ff, 32d481a389d93cacb8cbb3d18a141fa0c2949be99656c23e15755e81ebb55262, 0000000000000000000000000000000000000000000000000000000000013e7a )
459 GasRefunder.RefundedGasCosts( refundee=[Sender] 0xa4b10ac61e79ea1e150df70b8dda53391928fd14, contractAddress=[Receiver] TransparentUpgradeableProxy, success=True, gas=1464322, gasPrice=42644612987, amountPaid=53168733356252083 )

Account State Difference:

  Address   Before After State Difference Code
0x284c1875...5a4B9438b 271.47813737575250401 Eth271.424968642396251927 Eth0.053168733356252083
0x4c6f947A...C874F95Ef
(Arbitrum: Old Sequencer Inbox)
(SBI Crypto Pool)
596.672086528138358326 Eth596.673324301138358326 Eth0.001237773
0xa4b10ac6...91928fD14
(Arbitrum: Sequencer)
2.001645116971170185 Eth
Nonce: 78425
2.002029499776664317 Eth
Nonce: 78426
0.000384382805494132

Execution Trace

TransparentUpgradeableProxy.8a2df18d( )
  • SequencerInbox.addSequencerL2BatchFromOriginWithGasRefunder( transactions=0x0382040B07FF830102BE85E8D4A51000836ACFC09478F28D363533695458696B42577D2E1728CEA3D180C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000220757267D6C71FC0E42C3B92AF80EFD0000B6CC0301020907030805040600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000741D064000000000000000000000000000000000000000000000000000000000741D064000000000000000000000000000000000000000000000000000000000741D064000000000000000000000000000000000000000000000000000000000741D064000000000000000000000000000000000000000000000000000000000741E28E000000000000000000000000000000000000000000000000000000000741E7A2000000000000000000000000000000000000000000000000000000000741F8A0000000000000000000000000000000000000000000000000000000000741FEE0000000000000000000000000000000000000000000000000000000000742084000000000000000000000000000000000000000000000000000000000074213F800000000000000000000000000000000000000000000000000000000000000048BB30D378797B26AC1BF69FF751FFBF12F10C50ED83D5333A118B4F602674015021DD7F37C42405BC92A51789F0CD39DDC9BC5507961A85FA862DB0303D29EC327C5203206EEA1A01D1456C01791F07772833CA7C94110B86DC874E9148C508514289F09EFCBC9199B081422FC3EF10A790C056024D12DB704E6A51CB945A34D0000000000000000000000000000000000000000000000000000000000000004333A8EC049479960CF7F054D53A67EC152A9A61F35AD625D53B924B5FD7AE5A735816B507EE989730E4BED5D4DAF0152880A87B398E8B2E4C5F29821578171AA0039B026AF3DEC87A20303FF937D3FE06C34CDFDCE7CC7FD39D34136C0675A33195F0792556D8FCB1AD871DB386BF011DD2A85924458E181230C1F2FE8F6969F36DD1CF2D7289EA72CAF286272AE02B3780838398D52995C457296C31FBB5A8B0B774488F3D7122CF50CEA881914BA5C6B20F432F9BA47FD693C3CE9F7303B52010382040B07FF830102BF85E8D4A51000836ACFC0945AB0B1E2604D4B708721BC3CD1CE962958B4297E80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000074D0C0518667458577264B2AAC15152B000013970201080906050400070203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000018F260200000000000000000000000000000000000000000000000000000000018FBAA300000000000000000000000000000000000000000000000000000000018FBAA3000000000000000000000000000000000000000000000000000000000191434900000000000000000000000000000000000000000000000000000000019143490000000000000000000000000000000000000000000000000000000001934EF80000000000000000000000000000000000000000000000000000000001934EF80000000000000000000000000000000000000000000000000000000001934EF80000000000000000000000000000000000000000000000000000000001934EF8000000000000000000000000000000000000000000000000000000000193805A0000000000000000000000000000000000000000000000000000000000000004A3EA23970A1EC177E0F1C30FA2FEDF0BA94CBA965DDF74421F98A4AE9DE447C9E6E85A1F0B7F5C4AB0CCCEE548EA06CEC4DB3FFDEF0C95E62E4D2E6964778ACC655787ED8929AA978A5494AEBC553D7DEBAF2A8B6CEEEE05981E36190C62A4901409388E548DCA7CE402598AE0533140A067C3A605DB176306FAB587D112EBC10000000000000000000000000000000000000000000000000000000000000004590CA541427569D894984698CE3EE07F55A26B80150B23AC53B98314910752A6366889DBD581A4710B548D862C088C81C305D1F105BF728E7B274C0775FA1BA33A08883FDB0755928CE4F6157B1A092894AF0C4ACD8C9B5AE4865367E9B6E77B46F6BB304A7C7984C6A0F4AEAFB20CA86188CE99B0AEAC1945F917EDFB79680098078DBD3B0A846C0E5E1BDDEB7AFB8EDAED291B1530A77169234821812E89F8604E3DCD7DA1C9D3392D22BD2DF3CC3376C2D8C9C8CDFAF7F1FDFD4787E37612010382032907FF820452843B52DFEC8323AD9B94737EAF14061FE68F04FF4CA8205ACF538555FCC8809EFBFD7100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000034E5000000000000000000000000000000000000000000000000000000000000439C00000000000000000000000000000000000000000000000000000000000048F300000000000000000000000000000000000000000000000000000000000048F400000000000000000000000000000000000000000000000000000000000048F5000000000000000000000000000000000000000000000000000000000000622B000000000000000000000000000000000000000000000000000000000000622D0000000000000000000000000000000000000000000000000000000000000AE20000000000000000000000000000000000000000000000000000000000000FD700000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011AA96B0EA8252FCD358072C8C718641022EAFE9F90F636B2ACDED602C06F119C4CD8E3F55ECE8AA2E1F396CC1975C91B181DDD5573FF3C06ECC6A1209DF6DA0C010381A707FF36843B52DFEC8309ECD99482AF49447D8A07E3BD95BD0D56F35241523FBAB180095EA7B30000000000000000000000004C56DBCC056655B8813539AF9C819AE128C07E17FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE69F38601036CBF81E17B3A07A562949756C8B456BA2BAB90936F46220F4AE2151048F5E4C7B644F2E5E34809911443409B282F8C8B1A9627B50FFCA371EB6000382040A07FF82137685E8D4A51000836ACFC0949C65BC9C18F754129BA00C5298B539E69A32102D80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000C3087C6270E39B90F7F591EE46657B6D00003E7A0608060305040100070209000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000050DFB5CF5000000000000000000000000000000000000000000000000000000050E40E33C0000000000000000000000000000000000000000000000000000000510D92ECA0000000000000000000000000000000000000000000000000000000510D92ECA0000000000000000000000000000000000000000000000000000000512F56B4A0000000000000000000000000000000000000000000000000000000514744280000000000000000000000000000000000000000000000000000000051474428000000000000000000000000000000000000000000000000000000005149785840000000000000000000000000000000000000000000000000000000514AED7ED0000000000000000000000000000000000000000000000000000000515F1BAC00000000000000000000000000000000000000000000000000000000000000004A897A72A2C7B296B6C16DD186DB8A80067EC3D763A25ECE4CA748CAA42924E503173C7C55BD63042CE0A1E3F863B2EF854D30655A84ACA4DFD8B69EE8F1D328A1464A0FA09F87B8D1EA739D5319B98744FCED832A09759949D47FA4AFB1DEAE4E3133D9FA20FA03A19C512406CF21969F70FBC464089E74FD523D9A48585D5DB000000000000000000000000000000000000000000000000000000000000000415F45F4AE69707880758B1FC815D54B30BA96E85B800CF16F2C44ACCA6CE30D35923BC879BCC9EAE56F79E01C78219C290B69E1D09374EB07528598EAF04EEAA12B2679E9E250A3615920B7AA321D2DA0935EF55688F4B132EB113B53128A2787889F32C71C1FB3F8AD23BC726482641C433DC816579A066BCBC835CF7184EE2D692254975819AFB1B57E151373AFC3D95A2B5725B09BC72CA51A4995085E8013DF88C59E913CE9463500048EEBF467FDFEF5022CA288421419559E37FCE372C000382018907FF824A15843BF5C644830C350094BCBD2568D54A44925542318972D3F46696E4ACE38005615A750000000000000000000000000000000000000000000000001AF46E9D0669200000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000085C662E000000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001F479EFBF80E31BF570B043F1C89A902ADD1102A597EF65EF59E5A5CCCB5619F9CB082FB27B9E2D648E9F91C5167CB4D15A43411C0A8B4EEEA0E42189D1AD8231A4000382018907FF822BC3843B9D32C7830C3500945D8E854F0FE0D55C4DBC32D5F3EC0734F2DA00268005615A750000000000000000000000000000000000000000000000001C8892E22C6964000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000008D9BB72600000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001F4E1871075AA123227ED7D843635C771F74735CCC26CCCD9A3EDE707A3F011446E67FF54E94133D9B94C7F028F42117F151D2DCFFA5EDBA62FB4338B9CB7E0E514000382028A07FF8238BF85014DC93802830F487794BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000218761A6D957D975BE472E0680EA45ADEF03CFB000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000104627DD56A000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A4394747C50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000001593174DC00000000000000000000000000000000000000000000000045600E9C1FA75E8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E5F89D715329F32AE3C7CBF3966F4BDEDDCCBD9B6AA57B77233BC4B12BFA4EC52DBBD612A843799387EF502E89AF13807DAA94B82C97EEB36BC2BB8B63A63EF1000382016A07FF8227BD85174876E800831AB3F0941B02DA8CB0D097EB8D57A175B88C7D8B47997506808803DBEE00000000000000000000000000000000000000000000000029A262DC46A950000000000000000000000000000000000000000000000000BD6E5563746D5B72C000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000097581C75940624FDCD1CE618C4D0F6073CEB9D220000000000000000000000000000000000000000000000000000000062A99C9A0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FEA7A6A0B346362BF88A9E4A88416B77A57D6C2A00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB103B4037BB384DF81E71E229A1547079025CAC62E6E7BAA6FE2908920ACDD725C3F8191098D743CEE6E30055E490BC9D4AFF33482A1167A08EC01035DE5DC6917000381AB07FF830239BF85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C0000000000000000000000000000000000000E0A000017CE0011B4D0015017100000000000000000000000000000000000000000000000000000000062A815F92B55BAF5F9BDA7A1004B368596B5D901FCF55100E8F1DF1E5C9D691EC496749B7B5EA8C39EE559F00BBAD06342181361E071E35A769BE77E503C9EA354D596F0000382016A07FF82037385174876E800831AB3F0941B02DA8CB0D097EB8D57A175B88C7D8B47997506808803DBEE00000000000000000000000000000000000000000000000006F05B59D3B2000000000000000000000000000000000000000000000000000000000000228D852000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000C91837D831BD9F0738ED4E538A2778689449F13F0000000000000000000000000000000000000000000000000000000062A99C9A0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB11D97BD368C09FC6EE0A79B75DC99742E4CC3B5C3228802CA37EFBC66DF10397435D0F7BAF93537E197816794DDD1B350D8E74EA713553189BFEC6C0E3778CE3201036707FF2C843B52DFEC8308A2F494E4B2DFC82977DD2DCE7E8D37895A6A8F50CBB4FB80C59203AFEDA90503B0F42E59416879C19C92595F8F610FDF11CADA46887C7BA48A22446B4FE6C939CEF232E0B191689490EEBBD5C5DFFC0AC53C7CD1A6839E50F9369A2F0003818907FF82011F843B52DFEC830892F494602E50ED10A90D324B35930EC0F8E5D3B28CD50980049878F30000000000000000000000000000000000000000000000000000000000000E6685F807D63ACBE3DD7DB5EFFAF7CBC896DDB6B5DF7357897DFBDC134FC2FB0E272488C659B1892818276D9F8017740D3E56A29751B087E1D803A53F1AE7CACAE40103818907FF822C5B843B52DFEC830C5D51940385F851060C09A552F1A28EA3F612660256CBAA800E752702000000000000000000000000000000000000000000000002D25A772E9AA29F8A75A2E27E3241DC49DCDAD496036A9048EBD9302DD520AA20304C7DF7B06AAA16035781FABF4C98E5FB44039FA833664110DE5EABB0497874161368074084771400036907FF82BE41843B9ACA008307A120949C628EB38415809589DD087DBC4BB7B3E8416C03831E5B1A0A38024D11F9D9BD34D30DD020C6FA3D49ED9C159CF9B00260446017837E613D67118EA3D231B5C3611373A7581604106835DD10C6BF5035CF89FB37F47D4E6F120003818807FF81D0843B52DFEC8308A0CE9404FF29F8F379B2AA7D79BA66CE76649334D83E4880A694FC3A00000000000000000000000000000000000000000000000000000000A8A8AB6A3FAE4C03BE47583C97E875274BD8894CDFEB68778F3BF8D6098BFA63AB032BBA08B1856D2A63FB053683A9C615374DE6708B1B4C7F6D1CF282404ADDDF90C611010381A707FF08843B52DFEC8309D5FA94FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980095EA7B3000000000000000000000000A867241CDC8D3B0C07C85CC06F25A0CD3B5474D8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D2FB6DF17F4665A4BF7729AC258A34CA33AF31DF6F36FAC7F0B879C7BEB00AF566BDEC6ACEEF970FF9E42794C0C04134A215EA4E88B2860127818C4250783E8010382040B07FF8301109485E8D4A51000836ACFC0947B9845A634822C543F5CE544DD7D7797B79A06B880C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000B73308060EB1A83D92ECC837E0E3183E000059070607050304000902080601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000005176589A93E6F0B600000000000000000000000000000000000000000000000051E17A1E61771B8600000000000000000000000000000000000000000000000052CFAF714FC62EF000000000000000000000000000000000000000000000000053362C967D578B80000000000000000000000000000000000000000000000000533AD0F51D5659C0000000000000000000000000000000000000000000000000533AD0F51D5659C000000000000000000000000000000000000000000000000053A5F278EAE6849000000000000000000000000000000000000000000000000053A5F278EAE6849000000000000000000000000000000000000000000000000053CD8ADE200EB5D980000000000000000000000000000000000000000000000053F523435536E7230000000000000000000000000000000000000000000000000000000000000000454DAAD5C982B87EDBDDB8B937D3130E8471250171DB580EAB61AFBEFE49DA40F476A6A1E6DCDDDCBE89D2EC103E3FFD3E3443F8BACC6E3408DAD3E2029622643F91D57BBE582BD673B6CDDFBD2F3735C9C31D6DF50B93E3C1B41D76944DE0BA61B7C97E176B9D175571F1AA88573B65F3D704425D73803865320A0E7E5F6D91500000000000000000000000000000000000000000000000000000000000000041DBF21A51D244E9119BC925B7B965E8DED18802A1CDA46E1DA63E623CC8DA4E6216650B10AA5C885C244802A74D80407D7B169DD835092A50FE4D7F6E3FE3C250CABF040703E556EFD32A3B321C2D0E90B294DC37A6872A6D7F8F2C38F54E4433A1C1E1D40F84AA27E94BC1B295685A6DEF4FBEDE799484EC53ECEAB67AD693A3B9403C1341B67A51E95E7F7C9B68EB9FD5795AD7AE35715B6F1A3011008692C349203C626E3ECF1D9E402B0C0899FA136058FB0554E348BC9AB35E6FB572AC7000382020A07FF82B83D85174876E800831AB3F09468B3465833FB72A70ECDF485E0E4C7BD8665FC45805AE401DC0000000000000000000000000000000000000000000000000000000062A83D1500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000E45023B4DF000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000565D82C9C9584D21AD8EE5A73B56CE71DACED7E200000000000000000000000000000000000000000000000014D1120D7B160000000000000000000000000000000000000000000000000000000000006785BD36000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AA0A1988A440442ACE84EB4C8870B1AE5533575353B002BB4D5E685A2E0A88912DBD7F5AD14A4FDD3CF4463A1199BF330AC0376B84C23E81C955B6EFCF3D2A3300036A07FF830108BA845EEAFFE0831082DE9400000000000B69EC332F49B7C4D2B101F93C3BED80A70944482AB5CF8ACB2B94880B67B416CB6541C24D0AD90D1C2D68D8742D056FECD5E80D6423AEE1360865D54515C07B0E5BBC2831F0FE280E2F2AB546CC675FA7FA468801038201E807FF28843B52DFEC831A5F9A943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EE70DD2FC000000000000000000000000000000000000000000000000000000000000014000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003826B850AB99B944CF6F7413200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007BC158C283525B269823A97556FE29813D51932B000000000000000000000000000000000000394B95D4B2D70776E7EF8600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8982713F90E3A870E2A22137442F0715B382AF2C1DDB7A98853B4B5CC12F38B7A43A033870B6A350BB1EC8707441AA2861CB6B03EA75541954DDFA9DB63C1114901036A07FF830108BB845EEAFFE08310A5B49400000000000B69EC332F49B7C4D2B101F93C3BED80A708C484FC96F7DF051C17628C492DDD7A1DD31F50C0EFA538FA928494C1C42680FFDACB034A65EDAD22953615EA6B77E9C086EB7277AD252D9556A5041619ECD565A1CD000381AB07FF830239C085174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C0000000000000000000000000000000000000E0C000017DE0011A8B4014FAAB40000000000000000000000000000000000000000000000000000000062A816095453209AF027195BD17831371FCEDB49FFDFCAA917AFF757AA2786F05A4E2C2C1B6D522C29DDEA7ADAD3A43D0FF5503EFC3B0D33275E5003B1C43CD33804FFF3000381A707FF08843B52DFEC830882ED948858F290E06B55B006B22D32067FA8756C2B33C5804D9E47A8000000000000000000000000DDAC9C604BA6BC4ACEC0FBB485B83F390ECF2F31000000000000000000000000000000000000000000000013D74534D950F80000360495BD1DF5F70B5EFA1B9481321943A10044FF3E04030A498A9D0AF1296E387BABEF8C90D88C5F85B490A74FF2AFA7DC461EC3A6E3DD4B5CDC0BBF67B7C87100038202CA07FF820FF385014DC93802830F487794BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000D65035D45CAE1DAC7A77A83789DAE45BEBA0FD98000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000144627DD56A000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000E46023E96600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000008AC7230489E8000000000000000000000000000000000000000000000000000000000002B256B14A000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F6000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001CCD61D94A02993B9E935BDAD3F10053A3EC1282CD29FD1DD0ADBBC0748D026F2F23418D27C0028C02CBE4F9C8E6CF1FBE81E15C00C06638116E566A0DCA5FF1000381CA07FF82644F85174876E800830FA8059487A4088BD721F83B6C2E5102E2FA47022CB1C8318011D9444A0000000000000000000000000867613BEEB5501C30E7A25EA88982C212F188710000000000000000000000000000000000000000000000000000000000000016000000000000000000000000D4266F8F82F7405429EE18559E548979D49160F380D7BF4E3E613CCA386F9D795AA0130EBF2EA2093C288360936515C1D9CC75A54FA43BD2EE76F21135F28756EE106E4F266C5489CCFC2A6734311C37CECBFEFE010381EB07FF83013EBA85174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E0C000017DE0011A990014FB0540000000000000000000000000000000000000000000000000000000062A8160B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007D7083D23F1949E7D809D0C3F5F9B1956EB96F166994B0CCA38F554F95A5A4DA6E3116C05C5189FDA64A8D304DE4F196551E4CC48D674DA5B45FD27964A947850E84010382016907FF826BA0843B52DFEC831E508594E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000D0DB388F32328915654E88DB4241EB45FA6ED5590000000000000000000000000000000000000000000000000000000062A816840000000000000000000000000000000000000000000000000D965FB74951320000000000000000000000000000000000000000000000000000000000436BEADE0000000000000000000000000000000000000000000000000000000000000000EF0C65C0BB4A15F115F5D2C5FE7701E2B468AE306076647636EBEC05ED78E28E102BC3AF0589E70294BD3C85985F93D0E4B864725D0DE140B7B1E71314524CEC010382040B07FF8301097B85E8D4A51000836ACFC0948C4308F7CBD7FB829645853CD188500D7DA8610A80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000017E94DCDE4FCEFCE3FD70621604B018500003E770400050703020406090108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000A7FC442400000000000000000000000000000000000000000000000000000000A7FC442400000000000000000000000000000000000000000000000000000000A814CA7100000000000000000000000000000000000000000000000000000000A81FA14300000000000000000000000000000000000000000000000000000000A846446400000000000000000000000000000000000000000000000000000000A846446400000000000000000000000000000000000000000000000000000000A846446400000000000000000000000000000000000000000000000000000000A8474C7D00000000000000000000000000000000000000000000000000000000A84BF1A100000000000000000000000000000000000000000000000000000000A84BF1A10000000000000000000000000000000000000000000000000000000000000004649D04EE871FFBA4F86445077C9A8E6C663DE0A8F1964C0411E478913A9B35C14E37294EDBD35CBA1270BD4DE33B16A9F51F97EE020E12962A157F17235B9C325DE6D2605DED5048E62DF80303C843B2A1CB966B6A514E0940A7EEFD16536210B158166A45ADC18DF984744A703AEB82A3FEE554BEC46E685D399C096DB0118F00000000000000000000000000000000000000000000000000000000000000047BC57BC52EE67277BC7C3D5E948422266CE2192F00096B0CBAF5BD8197D5ACD333B14BBC66CD6441AE7CE2D1821FC722853242918D8F15FACA285931991FC788171F0BA24B4163850D89BC7671F10C9BB8CD91BED7B38EBBF4E5B555182AE8B84CAC348FE8331C5CFA52A1AADCD4C34AABC5878E57647C2C1ACB982FFAE00DC358FF3AD9F1143760A6B1C1448F756E4BC39D582684957256088BC257D3F6F8E3777F93D4D644DB7C24A14CCB14CC67B935716888D9D104C2E77316BC08FE580F0003818A07FF822D65843B52DFEC8405E6FA58948E79C8607A28FE1EC3527991C89F1D9E36D1BAD980EE7524A4067395E99C124909A7E5DE0106BF306A277A92E691FE4F476C44DA36A4EC902AF10EB65D195677FBA6585597250C76003C4C0DEA5A13B052B931054B736E46315CBBF4713A8DC2F798F8399D4E76FF0FBD9D1182843EE06AC32E9F9E9CB8547B010382016907FF826BA1843B52DFEC831E50C494E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000D0DB388F32328915654E88DB4241EB45FA6ED5590000000000000000000000000000000000000000000000000000000062A816870000000000000000000000000000000000000000000000000C834924AE1B0980000000000000000000000000000000000000000000000000000000003E0CBA4500000000000000000000000000000000000000000000000000000000000000001AE9AC135ABCD3BDDE83E1ABB12DB9EBBB302AE80A45995B4517AF5BF79281A4754AC2282A3BD4327027914238F597A23BBB55879BBC1E734EA9AD8847454CF400038203C707FF10843B52DFEC8340A362949E6EF7F75AD88D4EDB4C9925C94B769C5B0D628180331239260000000000000000000000000000000000000000000000000000000000000CD9000000000000000000000000B5E89DC549B070CDD51FC18F1072AE9EC6E7A7C200000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000002E00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000347B5B7000000000000000000000000000000000000000000000000000000000347B5B8000000000000000000000000000000000000000000000000000000000347B5B9000000000000000000000000000000000000000000000000000000000347B5BA000000000000000000000000000000000000000000000000000000000347B5BB000000000000000000000000000000000000000000000000000000000347B5BC000000000000000000000000000000000000000000000000000000000347B5BD000000000000000000000000000000000000000000000000000000000347B5BE00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000041F20485B7879B46640A5074B1E68D17DEE6547002F83B5774D1A034D6E0D5F87E1C88D45B8D81C0D14BD10509FA0D52CE5F4AC1D4782D8A86FFAFF28B0F7F3AF91C000000000000000000000000000000000000000000000000000000000000006C0AF58E24674594287AC4EF1CBCFC48C3FA32CF32F58404E8C04CD4EE19209B7728AD0CD0396A1D86C4B83219FBA3136BC9BB0D42E4E8114776F9BC0EBF607B000381E907FF8211AE8477359400830F4240947F2CC67F056DF576028FE24B6588D60D252D14DC80C43ED2C80000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000044F5BAC2724A60E39FAB2E187F0AB74A39B3F6F12F3995F8E63E541E9CF4C0859D4D39274F726A4DC422220CCF9BEC83E1E1E728D734B0D5096E47698C20DE3C89599B94010382060707FF1B843B9ACA0083415F3894E8C97BF6D084880DE38AEC1A56D97ED9FDFA0C9B8006E75722000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE000000000000000000000000000000000000000000000000000000002F02FEFF00000000000000000000000000000000000000000000000000000000000000C00000000000000000000000000000000000000000000000000972323F042EA580000000000000000000000000DF1F9D389C3E25124B93D7BE5AEEB9B7436F7B7C00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000003200000000000000000000000007317A559DAFE4AB0F5587F8C2C4410513D040ACB000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000A4A7CEE8290510CCF9EB3AB03C1508D3B9769E8EE2CFD6FDCF00000000000000000000005D000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB90000000000000000000000000000000000000000000000000000000017817F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000660DE0023DFE38059138DF60F3EAEAD87771BB9F00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000124EF5DAB3A0000000000000000000000000000000000000000000000000000000017817F7F000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000000000000000000000000000000000000660DE0023DFE38059138DF60F3EAEAD87771BB9F00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000124EF5DAB3A000000000000000000000000000000000000000000000000000000002F13AF07000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001F40000000000000000000000000000000000000000000000000000000095D9181F90A8298F4F748E47FB592C3ED7BC40076405C624F3BE10BF92EFCB11056E1F20BD0825F62DF14BF66BF3DDBD05D608DA73E4563B39D865243EFEB207000382014807FF01843B52DFEC831047D2941B02DA8CB0D097EB8D57A175B88C7D8B47997506250F7FF36AB5000000000000000000000000000000000000000000000008B011FAF8E024C5840000000000000000000000000000000000000000000000000000000000000080000000000000000000000000E042B1E03E9BCB70AA136B14CED072DB19B395C70000000000000000000000000000000000000000000000000000000062A81CF7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000539BDE0D7DBD336B79148AA742883198BBF6034279B52CF4421F7550F4CBAB6686B7EC005AA9CD67D58D359826EF9CEF3818EDC97215E5E00B8D4B139979E1BEF29343543E1763319E638D70DE4C5C0A76202C2A00036C07FF09843B52DFEC83077BAE9480C67432656D59144CEFF962E8FAF8926599BCF88801F8A443F279E32E006C00F4D13FBB83FDE0CC42DF377E847E4C1D50FC16FFF0E64B9C760698DEB06A2D8E572D81C4D9DBD29FA1E5F1DD26B6CA5BE9BC8E3156F7AB4119B219FCC37D00038201C807FF55843B52DFEC831AAC5F943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EC9874170000000000000000000000000000000000000000000000000000000000000012000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000003BA98CC70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002CAF50B1770639C11993A35FA1800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038D6C62F77DAB0C6F0A7FC0000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC88DC42DB6DBFD81AD4F047CCD25BE8832E1B2352273E366452E65C36CB89EF58246440F8D46A1A8747B5C71B2446DDBE0AB584712C104B50F2C3BF59484264E93000381E907FF8204EA843B52DFEC8310718B9479A556EF2C5B613DB3DFA8797E6772C5AAF8683480D6F5195D00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000036020599B2020000EE020002E6030000000009502F900000000000095365CED804040302059A3102059A7B02059A3102010732020000EE00000000000000000000E4FCA57EA3222EEF8E5E5C6489C60B1D5D5634B06987178480B940DC945B816D20FA4DDED9A981422B3AF5F750D087F547B44B508DAE2800A66FBDAD0FA284A1010381EB07FF83013EBB85174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E0F000017DE0011ABF2014FB7660000000000000000000000000000000000000000000000000000000062A81615000000000000000000000000000000000000000000000000000000000000C57800000000000000000000000000000000000000000000000000000000000000006F4919912A98561ECCE349F62F9870D7686CD7C697FDD385AC2C8404590A985E49904FB1C98188D5582F18B615AC9F65A0DC755EFB785BC9DF178A9200EB018F000382040B07FF83010AF485E8D4A51000836ACFC0943607E46698D218B3A5CAE44BF381475C0A5E2CA780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000F6D9397093865A569A3B827FBE021B4E00016AF40405080706020300090104000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000001AACE1AE7D0000000000000000000000000000000000000000000000000000001ABD237BC20000000000000000000000000000000000000000000000000000001ABFFA46800000000000000000000000000000000000000000000000000000001AD63AD7E50000000000000000000000000000000000000000000000000000001AE079560D0000000000000000000000000000000000000000000000000000001AE68AB6400000000000000000000000000000000000000000000000000000001AE8ED10400000000000000000000000000000000000000000000000000000001AEA4C04000000000000000000000000000000000000000000000000000000001AECD81E820000000000000000000000000000000000000000000000000000001AEEA5E8400000000000000000000000000000000000000000000000000000000000000004E061173102214887CC38D39464A6CEB7D70307295E16FECF97DE4771AB630C0BD2A9379BBACFC2F04924ED88E0C0E1D39B6AD82EDB8066CB8A55F043FFE705D246710B65EF596ADC8B2452B7524C3E9290C2608F1665A46C151123C03B24413B652EE509E315CE07C6F8113F780B8BF4A6787E1538DDB61E9410151ED7E7363700000000000000000000000000000000000000000000000000000000000000042CBAD0484FC35949B7E9D9A9F68FC7BFC5B5895CA4F5EF1C383A05EB42E93C5D07E91A419F088E085E8228CD9B377EC464E7D60E80B20340BB7C35E0CC2469B1070F12AEEE60DCABB993C38E10A7FC91ADA3A0A9DE6698754907BA0CB08ABE5F3448FFE648B9C0F365088DFF8A31BD0160A1A9E80FD17A8DF4E8DD2759418BE3A48F02A679CF1E54B2A8EA716971C07362F28C017BE82B6FF2E505425129A7F865FC13F815C1B30BBF93946EB7F2EF55C475BDCF0AC713684AE5088E7D19ED09000382012907FF82F118844A2797E7831164A6943749C4F034022C39ECAFFABA182555D4508CACCC803D12A85A0000000000000000000000002C01362BE5C39A9039970C89A74FF2DFB04B57760000000000000000000000000000000000000000000000000004A451A50EE667E242BE5FF85A9E362924543C5DEEB31073299713FAA5AB0AF17312416E4D37D00000000000000000000000000000000000000000000000000002EB2193F2D7B30000000000000000000000000000000000000000000000000001B2F0FC6A02700000000000000000000000000000000000000000000000000000000062B1505FE598E3D08F21BA87BB1423FD5CFF4DE79A967B29AF6846F0346CC09AE167DEC433A21C07ED05A6F2135FF0B43BE598BC0456BD7F807593DA085BFDFE2C8D5364000382040A07FF82EDC685E8D4A51000836ACFC0942F45A77C5024EB546E9E7F445F266C0D3E71E61680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000008C76406B0B69D023AA5BBA5E5AA3100700003E7C0101050800070904060203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000002A14B480000000000000000000000000000000000000000000000000000000002A23F6C0000000000000000000000000000000000000000000000000000000002A252527000000000000000000000000000000000000000000000000000000002A321E92000000000000000000000000000000000000000000000000000000002A321E92000000000000000000000000000000000000000000000000000000002A408C86000000000000000000000000000000000000000000000000000000002A408C86000000000000000000000000000000000000000000000000000000002A408C86000000000000000000000000000000000000000000000000000000002A43D5C3000000000000000000000000000000000000000000000000000000002A4401E000000000000000000000000000000000000000000000000000000000000000046C8EDC86CFA43BA9B1040EAE798B37296F082BA5F30BBF79F0FFE36E4076D1F5B7BD770738256B99B55B0C6EC0A4125AADF0DF9C6B2DA3E54DB0A265FD866E97764BFB60105C6A8483018107DF0ED2F9F3885F328DA97E574D8BED1BC351CD694A3A6AC2B9B901FAC2ECCC8F3DF7BC996345D8CA59EBB1DD9330958269766BBA0000000000000000000000000000000000000000000000000000000000000004547087290E8FE1BE7CB31D6C71B6449E3B057EA4E7DBEE63B4DBBEBAF5EFDF6F12C9D3AC5869E53F417A57F546D47BF47F2933D7DCE1B9A20692D160238B39EE44632DE79D214BBEE8B11EA0FF6D1DE0E84D5243CBC453262BE4C7AC79E1800B73CEF3D5898941B844F3D3371B8F3D26198FA0D746028F8CCB5F7DAF5931C68C0488AEEDC751C1005FB28121FC830EEFA0D2C31FF5F1D9DFDE7BB66FD9811ADE593CB5892097026242F800CDEFB1C8D7BC5EDF9E2203FCB7359BF4CFFA9FC21D010381EA07FF822B7485174876E800831AB3F094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000AB84058D8366A14F2F3849521A7823E4BC96FD2F506261893CB6C92066B15B9F4B7B21166D014B9C66ECCAA13A4E2D48EF5175CF43BBC6C7B23DFD2EA79F6934306C2DD9000382012907FF82F119844A2797E78311708B943749C4F034022C39ECAFFABA182555D4508CACCC803D12A85A000000000000000000000000915A12AC34627906DC2FA6C15675A7CAE1BF60CD000000000000000000000000000000000000000000000000006EB99B76FEFC8882D5906A9F29B82E99FBC8F144E36A2001FA7F9B6909C377134EF28EDC7078C70000000000000000000000000000000000000000000000000002033002BFDE4300000000000000000000000000000000000000000000000000673FF4ED80AD150000000000000000000000000000000000000000000000000000018160A7DA1FAD7897127E1AAB15FFCF81A5297C02397C03E37C0A83342AB362101EA5A1DAEF0AA374D399CE6D162E16999E8BA6AA40969E35068A888FD57CAE64A715841EBA00038201EA07FF82010F843B52DFEC831D2081943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EC9874170000000000000000000000000000000000000000000000000000000000000012000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000003B9ACA0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018A546767CC24F7FEF979387DF400000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000039458236DD4EF545BD12E60000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB11EBD72ED1131E615EE0B52B57EB3D0B35F64B14A2BE8E6C0DE5A15EC7CC1251C334BDD8CF1622EF9EE95DE24679440BB6386CF281D3115B6AFD873B618A9C484010382030907FF820349843B52DFEC830EC32994737EAF14061FE68F04FF4CA8205ACF538555FCC88011EE3CF1000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000044FB00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000056DC0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000366DE8F8B8B5148793DE9D9D9967C8D3454494B5CEC916286204F0627DE360AA2A75839B0B6F034767D2D33E28AB8836CB34C7BDE0593F07A027FD4211C4B256F8000382027007FF0A843B52DFEC8311CCD99468B3465833FB72A70ECDF485E0E4C7BD8665FC458804D1F92DBB243EC4005AE401DC0000000000000000000000000000000000000000000000000000000062A816FF000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000E45023B4DF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F40000000000000000000000005908FDB0BEA504552A3A89C40D1C553A16DB0ACB0000000000000000000000000000000000000000000000000000000017D7840000000000000000000000000000000000000000000000000004D1F92DBB243EC4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412210E8A00000000000000000000000000000000000000000000000000000000C868E0A47355E58C8F18C842380006DA60776BDED6EA371EE45858DFD06712354D460540067F24FD3116F1CCF565976CC71BE1A05E1E997B3713F96192A93D1F000381EB07FF83013EBC85174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E0F000017D40011A846014F91BE0000000000000000000000000000000000000000000000000000000062A8161C000000000000000000000000000000000000000000000000000000000000C5790000000000000000000000000000000000000000000000000000000000000000C5314C8D9D79AE03ED193FF9B7E6E5852B3426845BB2EF545027755542F29EB562CB0C26A391C7A5BAB028212740328A72E4800681F717F3B9B0CB46127A8AF6010381A707FF34843B52DFEC830F059194FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000F7C86A5E1323E6EFB954B2E65EBBA9C300C40F38FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1A05D5E6F23AA0174D0214DA20D42D1F2C2C0BC1E25F7127DEF80E61B5EAD5205DF255E702C8CB3F15853CFF8DFA0AE56B61196C09272C60999E00F984780DE010381A807FF8198843B52DFEC83098B2B94A0459EDCAD5AAC14DC32775D22FF7BD33027CAC780A9059CBB00000000000000000000000091C64E87DBF2F7E4A4CAFDA0D432ADD13706887600000000000000000000000000000000000000000000006DA3F0BF308B911FB81D14D5292A80AB0ED3D080DF862D3295D61C7581E323682CB2BB2EA7E5474F064E01CB7BA3023047C68717282912DEC682010AC03D96798CDC03BDC34796AC60000382024707FF2A843B52DFEC8319C59F945A39174E7F2B669A51EC179EF49B3ECA7DDB96AB80372F657C0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000D6DDD6A42A5649DD92FCADA4F33F3241B85159A7DF2E8C443D8DE5CB7C8CBD01E98B6B665B64D26AE8D03048B5EBC52FD382DA43E228DB0CF04483A4512972726C085E8438583B2A430FFF70DC2C5DBBCCAE2ECF91471DCD307D80253F660531DF9F6D9A7F069BABDD6404B1FA3C5220048042091DBC6255DF637EB1EDEC1DD2EFE74DAD895B7C6C529A8E59BC38EAC5BF843E9C0C8FAF73473797E1CA9FE9C57E2969ED786AC94724F4633FA0D78FDF031E6239373D87C86C596B54F26148CDAB659DD60FD16E36DB23AB221D2ABF749A86EE3EF001627BF47BED35BCCF8F38145715FE0D91E34AEFD28DCDF9CBC7AE0DA76F48FC001CD99E2F775465F8819E9C1CB9D8BA72F521C095CD157B733AFA6FF6AE77BFE7BD0AC92839244EC5C86675038492CC73660229BC3308532726E85123BDF90750D0C43CF69F84D00C06AAC21F13625A6774C91595AF49FD53CEA559E9039EFA30DB1B265BF1F57C50954EB5A60A9DE8BB0196219FCBB09F0E52769A7936D13C07403362E8AD1D66A05BD91825084E2E2DD0EBC32DDF69E558E75535D473755D7A59D66F0449E8E639C03F69AE5CDC717947E145623465BFFACD6BB8AF7ED8AC48C9EEB1AA60121B497283E39AE687B9244C9E514165420E4C3847767CA355902C05A86EF52D9F0FBC873130103818707FF04843B52DFEC830A82E7944BAC8BCCBF0FC39E8CC086397C39578102C9C366802E1A7D4D00000000000000000000000000000000000000000000001265D1130FC8270D1E22EBBB4016B08D2FA772923B98CA91DE90533F348F40C827B69B4E3640A233ED282B4558EDC134C5A36BEB2AF4C5A171E8DE0D6578CB4A2691C91ED3C7B9765B00038201C907FF2B85014DC93800831E7CC5943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EC9874170000000000000000000000000000000000000000000000000000000000000012000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000001312D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003355598E780182DE1CCFC80000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8228AFD2759A75F1436BF52C4193800AFEA66C49864D0722EB6B23DCC3F5527ED01A69757883F07885A694F31B7F20AF1AE59CEFD731D242C2FAFF7B71CE0306E010381A807FF8199843B52DFEC83097F4594A0459EDCAD5AAC14DC32775D22FF7BD33027CAC780A9059CBB00000000000000000000000035BE01389A8B694197FFF20FA60AD2F02B05069200000000000000000000000000000000000000000000006A3BEC5CCEFB1E00003090A012B0715E9676C13F18DB71362E4A5DB160BC65CA6B023B9A480AE9C3440BCD8AC28B52763AA20998C9F35C868CED35612DCFCA28F334618190EA4CA4BF000381A707FF29843B52DFEC830ED5E994FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000F7C86A5E1323E6EFB954B2E65EBBA9C300C40F38FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD65BC19ACB85031A5F781BB0B21324CC37B006A26EAAF521B464FAD99CAA26809B600F119189522934EA04A1C7D1F4AB22D838A78E23F41BABC650A2A6FD812000382024907FF238435A4E900831A3DE194E5C7B4865D7F2B08FAADF3F6D392E6D6FA7B903C81870E912D97FC000000000000000000000000F17DC7D60EFA0A37B8C7B792EA541BB72F989C06000000000000000000000000642FFAB2752DF3BCE97083709F36080FB1482C80000000000000000000000000000000000000000000000000000000000000B3EA0000000000000000000000000000000000000000000000000000000062A7F0EE0000000000000000000000000000000000000000000000000000000063213AEE000000000000000000000000000000000000000000000000002FF62DB077C00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000DE289000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000C78AC9A8DB56E5E7F031854F3687DC62872B30300000000000000000000000000000000000000000000000000000000000000041F226F586825BFA7A811973F8E8366971966AF1E7322B9ED6BE7842AABA17E8F70A3284BC2AFB0E6980548839C3D97C7774FB0F8B1F885689F530B6D0272401801C00000000000000000000000000000000000000000000000000000000000000AC2F7C74D7E3071D3BB4928A993DEB03753500AE9A000E42A9A24436975FE6C753254BB929A527CC0EF52C4893AE30F0311EDDDBDA073E2D87E24398D67E49BE00038201E807FF1C843B52DFEC831B3CD9943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EE70DD2FC000000000000000000000000000000000000000000000000000000000000014000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C253F3AA307BD8F61124373C800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000087FAE57F1C1EFE7D6981FDE34740F382588E7B5200000000000000000000000000000000000038DD10ED00E7E448A741C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5E620F480000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB15D1401A0E47B6420C83D60A338A1479FA177B0C704B3D7DD6AFEA7BE18699A8728360B8DB13897164FB5974B5DB6FDADAC3D3722FB125E71C90C84A6B48BC0E600038201CA07FF8204E0843B52DFEC831ABC37943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EC9874170000000000000000000000000000000000000000000000000000000000000012000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000002D3D6BC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044C8734CF62A8BE56ECB430FE8800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038EC4BFBD944CDFD1FF2EC0000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC836D5B4BB1ED2D69E08BB7393DCE7C697E8CB569A406C1E99253AC299C7177BAA2554296910A44071996286532DC01B387E9A816BEEF2B2FAF3D7803A988FEAAA010381EB07FF83013EBD85174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E0F000017D10011A724014F6F180000000000000000000000000000000000000000000000000000000062A81622000000000000000000000000000000000000000000000000000000000000C57A0000000000000000000000000000000000000000000000000000000000000000F619C6CF76F9BF01DCCFEE85C6EF9AE6F4C995D37D1A26F344EF0786A7C6D49D510E6AEF58C3B29718DFEC2A25D1CFC6F066C4C76AFAA9F947B274E74EDA7B3B000381EB07FF83013EBE85174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E0F000017D10011A8E6014FA1E00000000000000000000000000000000000000000000000000000000062A8162400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007D71593FD22F32000EB134DC6070D53F8C7CD980490B0A2EC515BDB4E67A5452DD2E0CEEA6652AEFCAA5E47B0938F181911976710E71FA9ADD1A3AC5B23900E897CF010381EB07FF83013EBF85174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E0F000017D10011A882014FA1E00000000000000000000000000000000000000000000000000000000062A81625000000000000000000000000000000000000000000000000000000000000C57B0000000000000000000000000000000000000000000000000000000000007D718B7D57EFAEB58EADA880EEE63230A8331EF441EF5FA16751A3C123103AD489375A33879DF7059C344CB96EC9C5D260DF4E4607324CD79B1CF5D7D252B13FDB93010382012907FF820FCB843B52DFEC830F484294F7C86A5E1323E6EFB954B2E65EBBA9C300C40F3880CE9247430000001232810000000000005F87338300000000000062A82AC32329020266025B19D7A1F76403BC49996A0B7673A66FE13A1D285737E282FDD8CBA623F7084664CCBD9FFB6D9791CD0C45EC283795070FFCB639169EB2F64C58C066FACC6EA8000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000058B77253D2470B821BB0904963FA392A076D340A00000000000000000000000058B77253D2470B821BB0904963FA392A076D340A9FDE4505E99BA02F2A7EB2A5C5B48B0752956AF6EB3AC1E0973318BD1C78B7342B0EFE73941C2F4C39F5F1EC4A02130FDEE56BA89706CEFF21037827B194D74101036607FF82946A843B52DFEC830771CC949E80B4701CAB35C008D70D883BE51E0BA43F8D12390EB9F7F35F71E27B27CEA51F7489BDB39F54554EE9DA85E48E32EBB8F4C29A8D0F1F4E9F8DFAE939C520DCFFEF588A08B4D54C6D5CF1DF8CF5F9A366DCA4CBB9AB000382010907FF820FCC843B52DFEC830E78E594F7C86A5E1323E6EFB954B2E65EBBA9C300C40F38808302CE5A0000008CFBAF0000000000006FF7618B00000000000062A82B3C03C601232901C648E67489668DCAA12CBF5BB6687126EC39856FA4BF6FC1428F165EAACB5BEC15A7B10447EF0AAAD5C6E6C656180C475705286EBA021B77CE082C90501DA464000000000000000000000000000000000000000000000000000000000000001B000000000000001A55A5AAA3B462E8273BEE6BD813FEA4744F651A0000000001D79F588BF2C4FAA83ABEAF9D99356A0365996E5ADCA0A4439FB2B4045530B2E20E4E5BA12B850E51288D717BD92403CB2B4090975142A13EC2B204DCDBDCCEC8000381C907FF820385843B52DFEC83213D50943E455C3321EF4861DD8492D7FC099190A846458A808D6BE7510000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E989492BBE11C9E2D40D8F15D48FE64CF1CE76A14FE06AA2CF076E1B4A7121E39A55790CA17B2D7FD676327F4BA840865C37B4C3DE3E85C1EE8D49DBDB34F0FB0200038201CA07FF820227843B52DFEC831AB65C943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EC9874170000000000000000000000000000000000000000000000000000000000000012000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000061465800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000198487FB3CD19BC6EBBA32766000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038DCF0B60348E85FA8B98E0000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8725AAC7F63BF3011582F2F283B7148C17B876105A24837C77558D326495A9FA63C89E02BF9A67A951AB99FB8EC00083C02A1D65D1567ED7978E830C7103E6123000382010907FF820FCD843B52DFEC830E78D394F7C86A5E1323E6EFB954B2E65EBBA9C300C40F38808302CE5A0000005B8D800000000000006018D13A00000000000062A82B3C03C6012329018D295FEF596DD4D60C16B4343EA6C2D80220FAD0E15CE02E929F06D5324908671699BE545B74B17FB64AD8F4DF064BE2A2D2E8D33C64EE2396288115D4E7A325000000000000000000000000000000000000000000000000000000000000001B000000000000005A20D2477401D87DF1884506D49F9D21316D0BB90000000001D61BE0B5D3234F79955695CA68CE130CE27A0F8023A3425C51332104FB0DFB4C2AFE8EC2BBB609CA19E991FF438F7B550B1A9940CA91CA4DF45D1C54488C9E990103818907FF8202B1843B52DFEC8307D5E6941A5261041E9340579F58401389D6DEE185B6280480E7C6133B0000000000000000000000000000000000000000000000000000000000001D5C585C999406444521B55A97A43A88BAD7A8BF6FB4EE58E0A1401B8048906459DB5E018D0019FAC3F2706763058F393D802CCC0361D77C0F409763A72B952A5096000382014B07FF49843B52DFEC831450909409F77E8A13DE9A35A7231028187E9FD5DB8A2ACB830493E109C16CDE8A00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000055FB110D8D67CD78282C02004000000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027D664CEF15E610EEB5A00000000000000000000000000000000000000000000000000000000000000000000000050441934043F1027FC769A01C86C6F6E64C5793DBB77C93D0E2EE8CA05095A3B3A2848556AB671BFB1880A399551108E3D9918D268B45159AA7393718EC52ABA010381A707FF02843B52DFEC8309EA1A94539BDE0D7DBD336B79148AA742883198BBF6034280095EA7B3000000000000000000000000A0A89DB1C899C49F98E6326B764BAFCF167FC2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC837E2769CB04DFF533A2DBFA31D3F4DA02FFC7157E52984083883391707A5B0525E3112BF593A446E494CB6431E6B0FE2B8D2FFAA0010B04CD1DE349C7D786F010381EB07FF83013EC085174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E11000017D00011A6C0014F6F180000000000000000000000000000000000000000000000000000000062A8162C000000000000000000000000000000000000000000000000000000000000C57C000000000000000000000000000000000000000000000000000000000000000005BBDA5B1A1A4898D19F1897714A4DC8030F505A334911F605209F8F48595F1A46ED7F71A7F101348509DB244F27EDAD11951239DC5C004B6B95550A9BDA241201036407FF01843B52DFEC830761FC94B7247DF036BCECC3F4EB76ADA035E8CA5A531E10010F56E457A6F58F8E68F5B400EC0EC84E23CBD40D32A19558BB936A9E98C067061F30536DE50BDA20D7D8DDBE16C1710A78EDF9D9518219E1D55EDD64C4ABBE325001036407FF03843B52DFEC830761FC94498422E7C6EBE2CEF82F5A8CD46B2ACE64CEF68B01116E8D50214F0B65E4004D154558CFFBA0936B0220B00243301CE5405439F205B5409E562A2330AA990BCC84B3C46FF6E3E84212BBF6EA7A74A7B6E269A5805204010382016907FF826BA2843B52DFEC831E50C494E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000D0DB388F32328915654E88DB4241EB45FA6ED5590000000000000000000000000000000000000000000000000000000062A816AA0000000000000000000000000000000000000000000000001412DF2D3F37B000000000000000000000000000000000000000000000000000000000006370B0FA0000000000000000000000000000000000000000000000000000000000000000C82074047D454CFC646A50D39923F97AA842394A663C82CC33FC2219542954530CB02FD6A11F1B78A39955096E7C3B79816E323037AFCED07AA5C62FC22FAA6D010381EA07FF822B7585174876E800831AB3F094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000AB6D30CAF547F4D7C3D41A4484E8723C8EEB4E6BA6DF7E006887A5DA8AAFA1EFC9A82B3C2F350CE597BC7D417CAA8B4DFC5B54CE533E0ED1459C986596C6CD48C3C777B9000381E907FF8204EB843B52DFEC8312138F9479A556EF2C5B613DB3DFA8797E6772C5AAF8683480693A74930000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003D020599B2020002E6020000EE03000000000953955040000000000950316E770404020000000000000000400202059A3102059A7B020107320102059A7800000038894CBF991C759609C9A28CACD6B596F876E1CBDA72D77D50306AD7E81C1A365674160A5D8D88AE2ED333F6EDB6C7319506F86262347CFA2EA59280DC30E715010382040B07FF830102C085E8D4A51000836ACFC094CF17B68A40F10D3DCEEDD9A092F1DF331CE3D9DA80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000B647F600403DA7D44F028FB33467104600003E750402050601030807090400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000005EE395F0000000000000000000000000000000000000000000000000000000005EE395F0000000000000000000000000000000000000000000000000000000005EFCE7F8000000000000000000000000000000000000000000000000000000005F178282000000000000000000000000000000000000000000000000000000005F178282000000000000000000000000000000000000000000000000000000005F178282000000000000000000000000000000000000000000000000000000005F33E317000000000000000000000000000000000000000000000000000000005F33E317000000000000000000000000000000000000000000000000000000005F4ECDC0000000000000000000000000000000000000000000000000000000005F4ECDC000000000000000000000000000000000000000000000000000000000000000049E236B2B525659A79F3361CE37296544C70FE29CCC25693A155F165CC4A8B5CD8F68B6F1F9637A0BC2F0C0E52159F048C23A55BFFAA4FCE40D5806BDCDD536AAA328B49CD4AFE90212752F364B8A0A0240404C1B8A150B5DEF53880619521109888CC15AA1D9D58662BF47005A27F70366DFC18C46C73F790C0D81DC9E89FCD200000000000000000000000000000000000000000000000000000000000000043FC3B774AF99E533F505E9F43E21C2B5677493262CF52D5C6F6EE8F25FC6BDB37C905E31301536705D15085164E3865FEF989672AD2277C34E0731007389C3070FF2F97035259BCEC9E788430B7834B7EC0D953680444A778F89EC681BA8EC8B69463BEC83B41C8EAFA363584CB2C1B6ED4F1B6BEA9DB4CE739F167E22DC85EB59B977948DF8D2F218015E07A87F626C3CC369188D66442BD7AB84E828F23913489214E00CDD8F874AFCE8799128D50FCBA55A810691A71AFE543790E970D979000382028707FF05843B52DFEC83127F5494BA12222222228D8BA445958A75A0704D566BF2C8808BDB3913651E00FFD5ECFA7F3D4F33D62EDE0A97CF62EDE2000200000000000000000006000000000000000000000000B1155E86D1C910549B774CBDEFA67AF9B7DB0959000000000000000000000000B1155E86D1C910549B774CBDEFA67AF9B7DB09590000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000F97F4DF75117A78C1A5A0DBB814AF92458539FB400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000BB93A54DFB44479000000000000000000000000000000000000000000000022D63F0EFCF20D44790000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000001265D1130FC8270D1EC49DBC982A60C480E75E487CBCE6EEA900E4CCE84736084820EE49DC2BD2EBAB1246DFD5456D9D37B8AC8F9D1171DCA7510BD1F736C2B29B0182CD154484040601036607FF82BE42843B9ACA008307A1209461DD011FF1951865B87CFCDCE17F61B4EB531E5501105EAC1D8876987910598A12A1E78160987A263B6D91D814BD20EFE6F0A10077154B61422A90F124A2BC49EF2EF7D282F1FC7552E5D98FE7C4D391A9412D20F0BA010381A707FF4B843B52DFEC8309302B94642FFAB2752DF3BCE97083709F36080FB1482C8080A22CB465000000000000000000000000E5C7B4865D7F2B08FAADF3F6D392E6D6FA7B903C0000000000000000000000000000000000000000000000000000000000000001B17EDF95C0B319AB0B2A49DF2750593C6D737BEA3948B36C5D2A5C29BB09F2FC45CB4A058142B80A57EBBDC69B2BF45754CB73C8D67277D46AF3558DC1C1B4A6000381E907FF8212AB844438E7E98316E36094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030177D00A52EF6F800000000000000000000000000000000000000000000000000000000EE6B28002BF335E6A34FBCF7CF0821A1C68AA9B7931BA4D16DAC0E16211F78F0AC65774A1444E194D8E1826D17225C4AA7AD6D10CCCAB66D1BFE9EB9E87610E10F6F32E4010382010807FF07843B52DFEC8309D73B94BED32937D8A5D1421241F52809908F1A17D75BDB1C0D39C6E45D4554482D55534400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000006D600000000000000000000000000000000000000000000000000000000000155CC07E9877682D5CB4E9147AE2890077815B519B39D582DB2BADEDF681212C28BCCF6796B59C0229127A8AA51021A6F06DC530058AEF2102E8D8160264900437E2C301036A07FF830108BC845EEAFFE08311235A9400000000000B69EC332F49B7C4D2B101F93C3BED800C10460453A5B58A892E5E9A289EC0731544F7BE11A82D98C93C620C3EF207CD8A1AFCCA2C9AFFEFF1E4513DBD44C67A69A23ED616DBC7D171533A070981F7584047EB0C010382040A07FF82EDC785E8D4A51000836ACFC0942F45A77C5024EB546E9E7F445F266C0D3E71E61680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000008C76406B0B69D023AA5BBA5E5AA3100700003E7C0201050608070400090302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000002A23F6C0000000000000000000000000000000000000000000000000000000002A23F6C0000000000000000000000000000000000000000000000000000000002A4BA300000000000000000000000000000000000000000000000000000000002A4DAA56000000000000000000000000000000000000000000000000000000002A4DAA56000000000000000000000000000000000000000000000000000000002A4F8607000000000000000000000000000000000000000000000000000000002A4FD4FF000000000000000000000000000000000000000000000000000000002A53D2F3000000000000000000000000000000000000000000000000000000002A56993F000000000000000000000000000000000000000000000000000000002A5B259B00000000000000000000000000000000000000000000000000000000000000040B010EA647CB732BA7944716F12550B8F98DA87E9E043650FE17670CF3401F84744B8DEE8C8749339B5952F9F39711DE6CE99B727A24173AA4A95A074FE85597FA0D651A5BA9568E9F817C40B2B2DBF0418F8C068933A7B1F76221E13B5F9BE7217CB8B28C09AE56FA0159FAEF3515158DEC26ABB358A832FC7A5C9ECB0A85DC0000000000000000000000000000000000000000000000000000000000000004017FAD0ABD1BA1BBC85B7ACFCE27063A634BAFFF82A07FD3448BF58339B294D35C1147984862B96E1AB6197A5F3245C80E69ACFDF28B0CC4F64B32BDB2CB2E7D59DEB35A1209E6B614FD1428A542A9B3EBC412BEA838EDEB7C2EABFB270E0C3552E43CBD58F91DF40326B3D0D25E2D60EBB58DB7AC0942AD65203C4C9C25A19A54F0C0382AD6CE6240C10575FBA2E912CD8694B7D1B280C313497029332945FD17D546BCABBB00C3C8B36758299198387357643D2C251659BB66A4E7B8C68AB5010381E707FF17843B52DFEC83097DA694BED32937D8A5D1421241F52809908F1A17D75BDB80FDE2832F4554482D555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000EE6B2990E154ABA4049A0E7F883F488B14309458935A752EF26D1F294B6BCF8148A2336D4A49A50FE90A1444A752FB2F35A7BD2ADAC04121A009BD2A18190E7A75001A6C000382040B07FF83011A1985E8D4A51000836ACFC094BF1CD5CB759F8E21C98A4367B665F43D607E888580C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000055BD37A59C0B369591461F116F9A95C10000145B0500010803040506070902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000053C550000000000000000000000000000000000000000000000000000000000053DAC4000000000000000000000000000000000000000000000000000000000053E19A000000000000000000000000000000000000000000000000000000000053EC60000000000000000000000000000000000000000000000000000000000053EC60000000000000000000000000000000000000000000000000000000000053EC60000000000000000000000000000000000000000000000000000000000053EC60000000000000000000000000000000000000000000000000000000000053EC60000000000000000000000000000000000000000000000000000000000053EC60000000000000000000000000000000000000000000000000000000000053F04800000000000000000000000000000000000000000000000000000000000000041E6E1C7F744889F59625FC5ED9FE6E5D8F896E6246DFBDC37895EA6AC6DC8F2A4C85E487768826406242D36DCD34AF4AE7D4223FB8BAAEC007A044EA4CCFE0C8D7329F68557863534258756AC4130E8131CD79CB131EDEA92DD04A91C1F4C612FFDDD11E5E86F1BACE9A2F80731464F1F36E4EFD82CB2104286BADCD949F3AB8000000000000000000000000000000000000000000000000000000000000000401026FEB8A809705FC11E520FC1DA333FB0700FC3D53374E0AB367EEA55E116008169D53E3A1ABAAD9ADC8AED663889407CB90160772FD1B4A763B3C4B6232864664E474F1DA7AE93FD6CB2BFB28D628F12BBA51E7A215FE1CC9B5EDD0DB61313CD0C0E0A19F5305DD9E01AB4E487E48FB7ADE19EC356B561CF0275010B759B306117CE174EFD016BA7B287025E6F3A3F7DCD17C2D076389942C1858F628B4E341A691492F4210749C3C77753239D4DF5012B27D2A0E534B99F94B7D5FA825A5000381EA07FF822B7685174876E800831AB3F094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000AB5A2A2770726DB77FB817734B474899A9AAEE1AB92F7ADE803E42663E85AF503D667CC0181B6042790D093CDE188E256E489BF017014299E937C0CFCEC56681DDCA9ED6000381E907FF8273B8843BE7153F831E848094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029A2241AF62C000000000000000000000000000000000000000000000000000000000000CE87290D9A30A507C123956122D15DC020B9CEBD90F67277350C8C4B0633E0DD81215E6F7B1419C4B80D554D352935AE04C474CD6D2CAB8DEB11EEBE281894665D10C24D01036E07FF82ECBA843B52DFEC830F424094DF4BCBBF5F0A74957D9585DE9136F9E55160DB2D880371AD4CD5E8A0040026C19AF50DF709A7D60ADE5C458A5B96886395BA7663606DE9B0357433C42D5919A358389DE8C98F99103CB4ECB645C9DE95B5DC526C7EBDFD3B6A02B89FA571010382040B07FF83011A1A85E8D4A51000836ACFC094076577765A3E66DB410ECC1372D0B0DB503A42C580C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000001DAF840B23E94D5DCAD494E96683231C000042910406070003010805090402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000001530C37D0000000000000000000000000000000000000000000000000000000015449544000000000000000000000000000000000000000000000000000000001544954400000000000000000000000000000000000000000000000000000000155398400000000000000000000000000000000000000000000000000000000015539840000000000000000000000000000000000000000000000000000000001554589800000000000000000000000000000000000000000000000000000000155458980000000000000000000000000000000000000000000000000000000015545898000000000000000000000000000000000000000000000000000000001556A580000000000000000000000000000000000000000000000000000000001556A5800000000000000000000000000000000000000000000000000000000000000004B74E8C097EEA9178F37C5E19C14575C2F9E891B3CC183C45C1A723CD2B23C17459C823ECF6C2851D934FF995B2712878A8122ADF21892DC606D2687651A32FC5A16F31F52B1594E94E6FA5D7DF1B4633E0E050D4E9B477D31C1BD4FFE1279F041A0501D13CC664176C3A242A61B027A094E832AF604BBCC610CDCAB1421E249000000000000000000000000000000000000000000000000000000000000000042BF156C7C072ADED612DA456B7EA7137341B4A5847C8F9FCEFDD4ED0F13008C41D343F705E59A6E50D965B76CDCD9EF0E355A2EFB4E00C8A52B0CD8D2D4EFDCB476F4777254EEF0B0397FEB14CE5E5B1D8464ADFF2294403957F2CBADB85D6434489B0B57009FBDBE5A9A4A97C1437A7F3D0348B55A278F3D3E145ADD139CC203FA5D375B32408581760587AABD3DBA27A569D29BBA10EB2A71E744AA12A354E32B0701858CBD8D85943C1C455D3FB97345E7CC613FBE41104267DF813868680000382040B07FF830102C185E8D4A51000836ACFC094EFC5061B7A8AEF31F789F1BA5B3B8256674F2B7180C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000E193445CE0BAE19053668642A3CB19770000F45D0509080407000306010502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000015601D49000000000000000000000000000000000000000000000000000000001563FB63000000000000000000000000000000000000000000000000000000001563FB6300000000000000000000000000000000000000000000000000000000156A7BA00000000000000000000000000000000000000000000000000000000015721CC00000000000000000000000000000000000000000000000000000000015721CC00000000000000000000000000000000000000000000000000000000015752A00000000000000000000000000000000000000000000000000000000001576B0A000000000000000000000000000000000000000000000000000000000157BD5DA00000000000000000000000000000000000000000000000000000000158E6CDE00000000000000000000000000000000000000000000000000000000000000046E5B2A0C364FFDDB2005FECAF40399159E1DA2C5AFB4CCAA40605B9B37A9A6EA2C8D740DA2CA16BEA43B4AA4769C7223BE82F8D88161B7A4DD413DDFDFC64A96398147ACD9B05983D6CD08121EC59884496945282A81F212AB2FA8A5095D46973BDA14F191352B2FBD601F0654966923E434C2476CBA56DC122AD652E5CAD4110000000000000000000000000000000000000000000000000000000000000004747B6F2FF8907D98419540BC5236A79CD02D10940867D7A0DC5BE0DEFE2A2D793D6FEF0842FB05A94304508197751B42E768293E56D8462233D999BBAF1601980968E18594C986CE0ACF62B868B6D06A2630788024BA6B45C30E962446987079790EF6A69202165F72827D3D0F035A2BC041AD53A6BF6503B0D424EA34A472F288E4DDF4E5C7140CD247D66EEB87E26CAFB9DCC6DA62C592C6753A014C41ACC732365D82AA1554B7F4C4F66953294EDD0D8A0CDC1DDA9751A99879325AF91128000382040B07FF830105DF85E8D4A51000836ACFC0942489462E64EA205386B7B8737609B3701047A77D80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000771F22C5199A85AEBBD9EBA74FBDEC83000013DD0306090108000502030704000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000003C120F41900000000000000000000000000000000000000000000000000000003C54B40DE00000000000000000000000000000000000000000000000000000003C7F05E6A00000000000000000000000000000000000000000000000000000003C7F05E6A00000000000000000000000000000000000000000000000000000003C7F05E6A00000000000000000000000000000000000000000000000000000003C8C0A25000000000000000000000000000000000000000000000000000000003C8C0A25000000000000000000000000000000000000000000000000000000003CE7E344F00000000000000000000000000000000000000000000000000000003D003638900000000000000000000000000000000000000000000000000000003D2A8811500000000000000000000000000000000000000000000000000000000000000043865F00A1314DFC62619BE045D980B6BDB7DBD5D50B75D1BEC171D8BB363FAF6BD65EC1A8377429C459EC5C389797E82F04E74DEA2C2B92DB7AB4BBC0B212C8E8387B627E7FBCEEA9137DC02605E0897B37A9FAECA2A663E92809488BF2006DFCB7155CFF514C9FD310CB32841AD3AB334886C3EBACE4FB5C0F77D605BD9A74500000000000000000000000000000000000000000000000000000000000000042B6753F9DB0C91F0CDB74DCC28EFF5CDBB9BC46969175686084028D776CF22D0698616319DEF36EB7341AF5E798E387318C382F04C3B8691F1509280C1D650123C59082C7D1922F03B82845196A6EA489D3CB9013E9772C1D476678B40F69AFF3B79557951D52F723AD00A69D8038D4E8C53D69D9AC511EA1E9131FF81E7545611183A8203B4881BD91D008D5EA322270FC31482CBA7A2EED44D85EDD832529373F0D99EF61F50E1D9810343F12E21638AA9E57DD28D1B526D12D3A83F4CD94F01038202E907FF82FD16843B52DFEC830F787894E195A15533C01C8CD6B28F09066842486F80F8F280CC064C8C00000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000962EE88DCF981354F616D6AE6325B8A8DBFC341000000000000000000000000083D2DDF29EFA3FAC1E86DC3B935A64A63A9C53CF00000000000000000000000000000000000000000000000000000000000000024554482D555344000000000000000000000000000000000000000000000000004554482D5553440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000001AD8667A490000000000000000000000000000000000000000000000000000001ADC81AA4646C5B6809B4DFBA80F4FF52D7FFA61D36BC0D2262714CFA9D6929D45DAE920ED3EAAC6F6498B1ECBBB77CFBDA76F08295A7418B1BF1A02B7B241E65FB0439879000381A707FF10843B52DFEC830BE58594FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000C36442B4A4522E871399CD717ABDD847AB11FE88FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCDD0544AE98C1375B30DE2D3D4A7AC6CA7A10616E4710AF03EA6DBA964DB9F807E9AA879DFD60699B6CCBA3D8290CF96DF25D4E488DCFEF92900446C8E27FFBB000382020907FF820161843B52DFEC830BF72C94095FBF78C06073B1E052DA9220D71400C544FF1A80D4AD055F000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000E19000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001E00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000028EB54EF2397AED0AFB26B3CCA49CD9316B2AB9DACC0F421BA65421ED525A30863D4875A9859168640A3520712E00C35FD04E77E4441E0777EEBEC62357CE25A5010381EA07FF822B7785174876E800831AB3F094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000AB2C80A08C8DCD6FEBF555997D64699BBBFEFE7FBF1868B5C3935501A31F3CCB77F1CC5B434F16B5E67A52A6B553521617FA6190B2EA1C740F4E9A52A3C810B8FFC48027000382020A07FF82B83E85174876E800831AB3F09468B3465833FB72A70ECDF485E0E4C7BD8665FC45805AE401DC0000000000000000000000000000000000000000000000000000000062A83D5200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000E404E45AAF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000565D82C9C9584D21AD8EE5A73B56CE71DACED7E200000000000000000000000000000000000000000000000014D1120D7B1600000000000000000000000000000000000000000000000000000000000066C441CB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000838225026E4935D43CFD16BD212855BB096FEF30D1D998955E3BE2545CA309B25170322DF91CA9D5D66745DD70A79DECFD13E89C77895E364F24736560A45DD701038202CA07FF820FF485014DC93802830F487794BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000D65035D45CAE1DAC7A77A83789DAE45BEBA0FD98000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000144627DD56A000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000E46023E96600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000008AC7230489E8000000000000000000000000000000000000000000000000000000000002B0326B61000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F6000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C2D80185832BA6BE683F3D286E6340B65C72ABB4CE3813981541F4C907E5918062CE3070C4FB5D23451CBC5C01AD9FCC28E9AED92515A3AC6B73BDF7DABDE48D010382024907FF2E843B52DFEC8311454D94E5C7B4865D7F2B08FAADF3F6D392E6D6FA7B903C81870E912D97FC000000000000000000000000F17DC7D60EFA0A37B8C7B792EA541BB72F989C06000000000000000000000000642FFAB2752DF3BCE97083709F36080FB1482C80000000000000000000000000000000000000000000000000000000000000B49C0000000000000000000000000000000000000000000000000000000062A7F0760000000000000000000000000000000000000000000000000000000063213A76000000000000000000000000000000000000000000000000002FF62DB077C00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000DE280700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000E221F2FB3833CF228CC32DFF0241AA2A45695CD100000000000000000000000000000000000000000000000000000000000000413BB9F3B3810530C9D20A5612FD3FA607B8886AA5D673EC07C7F06C57720834C44696BAB15D19A68FBAB50D30F978C4FDB9F336E374C8EB5DDE88BEBA4CC73D2D1C000000000000000000000000000000000000000000000000000000000000004476BD51E4A6E37A6CA6D6B4F8CDAFC7EC8F465EE9A951AB1A49D60EEF823EAA2B4F843102234AA70197DCC49817832CE89C9E3F4BCD4628455D3164AE688B6A0082028A07FF8238C085014DC93802830F487794BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000218761A6D957D975BE472E0680EA45ADEF03CFB000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000104627DD56A000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A4394747C5000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004563918244F400000000000000000000000000000000000000000000000000000000000157DB0434000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007EBF709B87EE678E0BBE4CB935C64B2FF012C5BF296489808F4245E5319D9F26648F0FBDD1AFB779E71E7A361C6D502072E6B372B728765404D158E6A1838F660181AB07FF830239C185174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C0000000000000000000000000000000000000E10000017CA00119AA4014F5B400000000000000000000000000000000000000000000000000000000062A81642F98A3D21969D7A02454064CAEE930069BF3783727250CDB7853053C83C9A623D290EECC33AC8449DEA2B2F2EB0F9EDF1320C3FBC72F6D4A03596515C5BD0347400038202EA07FF82363A85014DC93802830FB0D994BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006FD9D63FA34644454808E188956191AB016F1806000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000164627DD56A0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010438ED173900000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000ABC1CBE900000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F60000000000000000000000000000000000000000000000000000000062A81898000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031E9E65AEC156F550823041034EF348BB6CFAF22DB553AE85F068C6E3FD0F0CB15FDDDE2D248A470DF5DCE16FC8A500DEC84D22C021150748635F024BD333926000382016907FF820C688483B2DCA0830E244A94F8D88D63ED3A2104E664AE8715FC9F80ABBA864D80ED7437080000000000000000000000001B02DA8CB0D097EB8D57A175B88C7D8B47997506000000000000000000000000000000000000000000000000257853B1DD8E000000000000000000000000000000000000000000000000000000000000B992419000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000062A81651000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC86FFC5EE8DC3C6B30C82E8F9422B4679CAF5605813B1841489EF7153D61C089B5200376A6F011D76F1F49D11A1C3E745C2EC7567A7E0DFFF8BB6BBEFC02366804010382016A07FF82037485174876E800831AB3F0941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED17390000000000000000000000000000000000000000000000000853A0D2313C0000000000000000000000000000000000000000000000000000000000002928CE8C00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000C91837D831BD9F0738ED4E538A2778689449F13F0000000000000000000000000000000000000000000000000000000062A99CE3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB96B5520E34107A677313EAFCBD5F5DD6E2AE88352B1F888693B5171CB574778540EFD6030AA393C4F0C902572D840DEF5094C19FBC4668DF9F48B5C755DC2746E010382016907FF8212AC844438E7E98316E360941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED173900000000000000000000000000000000000000000000000028FC0359D433F99900000000000000000000000000000000000000000000000000000000CA88CACD00000000000000000000000000000000000000000000000000000000000000A000000000000000000000000088928FF265A144AEF2C5E228D536D9E477A68CFC0000000000000000000000000000000000000000000000000000000062A8189B000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8A9108C72C58AE811D7BB17736B00B44462C691F6F41B57FBD2C99D1C063087D516DA573873AE4040682B8FAB86C6BB558DDAEC0316A576BEFD2DDE2ECBBA09EE010381C907FF821626843B52DFEC832DC6C0946A186D6D8B87EEA2F14964D9C0F0313DB16D1BA780E5EDB0D700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000006124FEE993BC000000000000000000000000000000000000000000000000000000000001E11B7848252FFD625ADA569B6F4CDC506FEF6F3052102A985E65EFD47C2918CCDB01A718354743B83300A3B265CC46FF2C924CA6D1703270E93515160773306CD8588E00010382040B07FF830102C285E8D4A51000836ACFC0940050D50CECC09CE311D4E0AB14377BFCD0397AF780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000009E69D7EE25C4BBBBB119859635E1884300002FB30607080500090106040203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000001716000000000000000000000000000000000000000000000000000000000000171C000000000000000000000000000000000000000000000000000000000000171C0000000000000000000000000000000000000000000000000000000000001731000000000000000000000000000000000000000000000000000000000000173300000000000000000000000000000000000000000000000000000000000017330000000000000000000000000000000000000000000000000000000000001737000000000000000000000000000000000000000000000000000000000000173B000000000000000000000000000000000000000000000000000000000000173B000000000000000000000000000000000000000000000000000000000000173C00000000000000000000000000000000000000000000000000000000000000049D681AF6A28183E6D25C915859F8DB5AEF59FC380E23ADF19F027CE5A78E64793D7BE9F856B5617B38C6AFAAC83FC7AA3D78473A6DB9C8F4D7DC261C289EDBA17CC86A1F8D9615DEDD5033869CB4A581F8479D18CE117A9B238711E1DBAAAE4444BDF7CAC41F5639C5E860D755B810D7A2E341A908421AAC6CEE86B6A44EB923000000000000000000000000000000000000000000000000000000000000000408691645597DED9B8D54EFEA0731B806CFA2743748CC8595EC5805D9AE5FBDA16EBB6BBF47F93F2323165A71D106BA0671224AEAEC04AC0061F3E7BC37FEF1295F98406C9FA87D187C38E5D9E58690DE5581A2FE4A2D0F4407D3B687715F31835CD381ECC0A20241A6C3E7F4261F53F56982D3BB5B9A80C0E6D60F2D44B98F0548C0FCEA41012ED0BCBE019B2383C0ABD6E17003A1F3A7D73932F262E3BD8A887D95941B18170CE91DBD728CBDBA8A952F222F5D315562D8D23F5AE5BAEE4760000381EA07FF822B7885174876E800831AB3F094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000AAE43436AA8E754BC2F5D5A54C423051BBC4EC0115669BF66AEF7D86DCC2BEEAF2929FFB5108F352F3A0628B2EB3CCC6F7A99D83B21A032D5534D612251A1EC6ABE2886100038202EA07FF82363B85014DC93802830FB0D994BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006FD9D63FA34644454808E188956191AB016F1806000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000164627DD56A0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010438ED173900000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000AB6503AA00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F60000000000000000000000000000000000000000000000000000000062A8189C000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042E7B761B24210D4ACA84147D332B2ADB75AFF32DF3CB637BFE29E9E78B1D70F07C7373FA0739BA5CC8B79D85764B0719CA6D839939765DACEBCF835E4F3D1FF000382016907FF8273B9843BE7153F830F4240941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED173900000000000000000000000000000000000000000000000029A2241AF62C000000000000000000000000000000000000000000000000000000000000CE2A96BB00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000C9F32F110E68F7C371280DB8A146EDEB283700A50000000000000000000000000000000000000000000000000000000062A81654000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC88BED7C0AE28DD80ECA069F9FFC3C559E3E555750B53FDF8126ED6EDD03A4DF8A109BABB042DCB5108CE4C8E8ED0B32C11A2D33E8BFFFFD1C1005F5AAA7E0A5AF010382014D07FF820228843B52DFEC831549789409F77E8A13DE9A35A7231028187E9FD5DB8A2ACB830493E109C16CDE8A00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000198487FB3CD19BC6EBBA32766000000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003C658C2A9242E761738B30000000000000000000000000000000000000000000000000000000000000000000000137EA7793DD388E886F88B3EA45B57470AAB35AC4CB678933D11E5FA0E3D1BD3C6062CE8AAAFF522F1945125E58E8E0300ED5065ABCBA4A768BB3A9E4763BCFF9010382040B07FF830102C385E8D4A51000836ACFC094942D00008D658DBB40745BBEC89A93C253F9B88280C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000C53BF610EB015FA9F4FAB204B58622E600003E7D0206090001080504020307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000001FE5456FCD7000000000000000000000000000000000000000000000000000001FEAC3D00C0000000000000000000000000000000000000000000000000000001FEF76705EA000000000000000000000000000000000000000000000000000001FF4A6DD440000000000000000000000000000000000000000000000000000001FF4A6DD440000000000000000000000000000000000000000000000000000001FF4A6DD440000000000000000000000000000000000000000000000000000001FF6492221F000000000000000000000000000000000000000000000000000001FF66CD0340000000000000000000000000000000000000000000000000000001FF924FEDC0000000000000000000000000000000000000000000000000000001FFD033B236000000000000000000000000000000000000000000000000000000000000000487764C33F14516CD806F121F65A9560D5B0F1228C94C6A606B73FBEDC2C7F3E4CB12ADF687845ADA515BBA1E47FADA3D24C11FD49A7E2B1D0CC70AC83320BE8A712597BE09B79DB3E2DC5EBF49EEE7C6236227580BBC8C0877468FD08FF05E8E3C0D7C640882B6B017152F37C1C1DCD4E190FBD63CAFD87D5EC7EC5633E29779000000000000000000000000000000000000000000000000000000000000000446CDF8B06BEFE2A259511BDC75E47B8F0C4C174E1149C015F2C747B63D1CF722012DD65903A06D64844CD170E8DE326FCF7163E7C1AE9DC76F84E1ECC5875EEF25E0C224AEE02E8536CF5D1ADD69DB663CE5D3485E5D5926B0EB49C0B3802FC6492B1C11411CC07D57E5BCD4F1D0B943EDE5B9E1C48D9F8B4CD2ED4BF389DF37144CE7CE6E579CC4330B2B423351B236F6BB966D19E5AF13294D009C98CD9EB650DB54792245AB8F23F3F2B1CF6C909276C83F793161CE7924B2DF85574C3F54010381EA07FF822B7985174876E800831AB3F094960EA3E3C7FB317332D990873D354E18D7645590805B41B9080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022B1C8C1227A000000000000000000000000000000000000000000000000000000000000AAE8025637D3799E293B22651DB02B07BDB60403D24ECE7A24243DFA8E769266682FD3E07BCF0BC1FE3DE4F270C7C192DA0F1ACAB0530CF5F2ED05178E8EA13F20C93D3A000382040B07FF8301097C85E8D4A51000836ACFC0948C4308F7CBD7FB829645853CD188500D7DA8610A80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000017E94DCDE4FCEFCE3FD70621604B018500003E770606020307050004090108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000A846446400000000000000000000000000000000000000000000000000000000A8474C7D00000000000000000000000000000000000000000000000000000000A84BF1A100000000000000000000000000000000000000000000000000000000A875673000000000000000000000000000000000000000000000000000000000A875673000000000000000000000000000000000000000000000000000000000A875673000000000000000000000000000000000000000000000000000000000A87EE86300000000000000000000000000000000000000000000000000000000A87EE86300000000000000000000000000000000000000000000000000000000A8EB688000000000000000000000000000000000000000000000000000000000A8EB68800000000000000000000000000000000000000000000000000000000000000004B50C3D66C27E49D4813D3A33FA0C775BAA7564502E901C64C7DDBB95900AE1F4F7CF75EA40894A69E0A526C778AAD22DBE468A8C3DF7B9F7168997C2A9424902E4228539E278DFC00473DEEA283E31CE176DC7135A2A5B0ECEC9ACD20E0B4DF77FCEE776A1D9389D430D7C949290E4B25E14C8BED575AB9A25F6641FEE61EF6600000000000000000000000000000000000000000000000000000000000000042E83B069C2A02EA1F4A09367A1B5F1CA64C542D420881E40A38DB8767AEFA68050BAFF19E01B8F50AE6271A1C7ECF460A26485BDAA55B64B8DC76276F4734FBC732D20578537953BA752ECEACB36CFC9E32230ABFEBE42AD30F1CD6F28E1155F4D17711B01F1A71C5ACCCB2F2731DA0C3C8A1E0C292A7311F513FD344B26F32A2097B20C59D52DDC63092956E7B567B29CC19896F5505FCEFF51868C7199CA0B348DE11F82511CFF9557E68F6AF645BA0E5D6C2AAEB3753E218D409F0CFC25B1000382040A07FF82EDC885E8D4A51000836ACFC0949B8DDCF800A7BFCDEBAD6D65514DE59160A2C9CC80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000017E1DE687DF661FD3F7EEB0D2CD65F500000F4520300040709030206080105000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000024299EFF0000000000000000000000000000000000000000000000000000000024299EFF00000000000000000000000000000000000000000000000000000000242EF0DC00000000000000000000000000000000000000000000000000000000243D5800000000000000000000000000000000000000000000000000000000002442E87A0000000000000000000000000000000000000000000000000000000024447ECB0000000000000000000000000000000000000000000000000000000024447ECB00000000000000000000000000000000000000000000000000000000244878F400000000000000000000000000000000000000000000000000000000244D7DE300000000000000000000000000000000000000000000000000000000245393640000000000000000000000000000000000000000000000000000000000000004B76517DAE0385B756D1FC788DD18BF96ED1D938D3CD4427B8BCDF78E352A276BB496712DF3254ADBAA77B96E984A1732CF823AF9505A4EE74CEB211EFAF32601A2916248F1B367BFA94B846E97B6446CF3DAC98F5878445492B0B0FE34DF4FEDB771DEE18E4B1FD73EF89A72BD0832AC6D845E6AFE55EE6E3D42583C192894C70000000000000000000000000000000000000000000000000000000000000004272E437380232E051FDAF1008B195EF6C4BEF7808BF10D6CF29175A5C6DDA0E55AA8AF863EA1D46DF335A8C2AB5E8466E90D91CFFECCB58070C480FDFB275DF11A0CD4376C10A86F58C60E5F9BA8D51DF04358BB68D923CAA8F05F472C4400CD0EC612B1BB3CA71FC3C655A440607449019DB519A1B3F42860BB89BEFC0E9D817AA095F9A297E59889DCCF5D64C09BBF267B840C4CCB78F25DB46E83087DC69A1F14FEA5EA668FB7E78DD5B3F2A41B0B133751A2AEE9BAF90290790792CE2A8B010382016907FF8273BA843BE7153F830F4240941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED173900000000000000000000000000000000000000000000000029A2241AF62C000000000000000000000000000000000000000000000000000000000000CDE8B63600000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000C9F32F110E68F7C371280DB8A146EDEB283700A50000000000000000000000000000000000000000000000000000000062A81659000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8C44C6EBF69A2C14B7EC1B7B598E350CD194917798A3C1C608921DB10BF53F7D014EDFD9BFDC27421492EA3FF2F7C36E93BF3F4F1A4CB0BF1D8911AEC4AAE92C7010382014707FF7B843B52DFEC8310BCA094ABBC5F99639C9B6BCB58544DDF04EFA6802F4064802D4BA6A700000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000002FAF0800000000000000000000000000000000000000000000000000098B0E0CBE588000000000000000000000000003CE24408B18D9AC7E018E8CFB9A1D09EE4A8C6CF0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB17F840E94919589F91588EFCDAA0500C187DD9B0BAE01243335BA0B7F221787556C3A22FDE60481037D14FA91473DDDDA430622B9FA2A9784E6CF47F5748A70B6000382026807FF13843B52DFEC831BD4399431D2678ED8EA62FC63D5ECFF713920F75167D0620310F2B953D900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000DA50826713A34675D331E56EA271EA64AE5936647ACAFDD91CB94AA0658C16D7AA8481ED3FEB6C44380069B310D602CA7DD0D29AE3B374315F85BCA16CC93B87E87C0D99466A9AB77E8387BB2FAB971C29F0D686DC3AA489DFAC1A2C7A63F7C83DAB47F1DBCA25C793255988ACEECC1A4262C8011B43165E4E6042C97F1EA725303ED3B5F7114643231F192028B29FEA420DE04A4E50666C2D262F42FBF3B8B7DBE5CAE9261FC5058563FD4F95AA85D0C820EEAB10D1B7AD36480C033C88FC6AC7E256774F00F761BEB0586A54901A709E558E4CA7C69FE4EC750F903E51E0D66CFF22EBDC423163C7A320CFF35A00BE803EAD14A49297AF6CB1A14BF645E5CB663A06B8C77F584FD78802889D1B84EBCA067FE782B6FF93EBABFA72557FEA6B42417B248B3914D22EFC17D9DDB6E8C79072444624B0C563B62EA683B91F3C25A4447FEF9CF3CF436A6156B791730FFBF658860306EE586FEDF38F2A22597333C5997C7F2DF2C53E4564E76E590D53279787DEC5C70AC1B8C6F586E8244E51F14C1DAA7B4CFB636EAB9C4751A8A6EA3C18293FAF6EFA9DFF155EFF74229AA3F65FAA2E7F4676753915091DFC0FD6302BDC7B54AF02697C1586E650B9E712E8A06317499B4A7033F456F28DF7DCD1AF8F2B6B3B3B8D2712F871247439C716421BC000382040B07FF8301059885E8D4A51000836ACFC094E5B5BE82015444C04B281CF4AFA6A99130ED83A280C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000C4126E58DD5664554B44A9C324E311130000C2170505010200040607030809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000198718195D00000000000000000000000000000000000000000000000000000019872BC4AF00000000000000000000000000000000000000000000000000000019872BC4AF000000000000000000000000000000000000000000000000000000199B149600000000000000000000000000000000000000000000000000000000199B149600000000000000000000000000000000000000000000000000000000199B149600000000000000000000000000000000000000000000000000000000199B14960000000000000000000000000000000000000000000000000000000019A86A3DD600000000000000000000000000000000000000000000000000000019B5BFE5AC00000000000000000000000000000000000000000000000000000019B77A72AF00000000000000000000000000000000000000000000000000000000000000049377956A5178C73A6C5B61D2F8BA312AC146C2058758C1DA7EE0D49779207D58A981E5C074F86B80FD30B01EF009ECFD97120DD3A8319C280C730C3151C8E2359E97409DD71C4A7C54B3541F385B5CA48859AEBF25B506ABE7C86994198BCDD17DB14BD42B2B4FEE5E74044B7F95DEE5DCE560DBD2B2D484D1FA1B9D823033A300000000000000000000000000000000000000000000000000000000000000045AE7025F3FB5A176DBB3C19F39EE11C7C1AAFFACF9499CD328A308C12710587D5A56B0755350FBB3837B271540270765BF68DF6E32D359D858D9245F4C64849772A2787E43576C7F81104242D0A9053B53E8CC8ADE7E1FC464C057748CB83CEF5FD74B335C4847F8FFB54FE9479B0A4A08DA47ADDCAF4868880B7A0E1AF21D3C54DFB30CDADA2A673D7BC6D988BB8894078B2031ED06EBFF5928B2C0E12848C36376DA44137070345DCF6A464D18190DC0B3FA4568B6AEE952307D6E5DCFB58700036B07FF0E843B52DFEC830773C69480C67432656D59144CEFF962E8FAF8926599BCF88764015DC9C8732E0098A081836227D0FE433F5928153A42DABF24E044F0DF32A1F916B57ADE7A663618D233BD17575E782EE178D24371C115D8583AC7A6E3B0B8689A817C3DDF0B30000381A707FF16843B52DFEC8309E9F694FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B30000000000000000000000001111111254FB6C44BAC0BED2854E76F90643097DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF459CE96114A27B36F1C3F1A2EF4D584BBAAEDB1216E271598577B8F583EA6FD0184683A8764BDD9B81F98CDC5FB51E1A2C57053CA05BDE80F2BFCF4AAA621DFB0103818907FF8202B2843B52DFEC8307D5E0941A5261041E9340579F58401389D6DEE185B6280480E7C6133B0000000000000000000000000000000000000000000000000000000000000DC1E3ABD6BF782B4A59826AD01240CA84B4F3A7B9E78DB7FCC8894DF19CC00D18672BD17AA02A7BDF91FA6C9B881F7D3A27D64637108B1372931875C603A04D89DC000382040A07FF82EDC985E8D4A51000836ACFC0943607E46698D218B3A5CAE44BF381475C0A5E2CA780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000F6D9397093865A569A3B827FBE021B4E00016AF40607050903040208000106000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000001ABFFA46800000000000000000000000000000000000000000000000000000001ACD7C5AA40000000000000000000000000000000000000000000000000000001ADB378AC00000000000000000000000000000000000000000000000000000001ADDE630000000000000000000000000000000000000000000000000000000001AE0FD80B70000000000000000000000000000000000000000000000000000001AE11855D50000000000000000000000000000000000000000000000000000001AE11855D50000000000000000000000000000000000000000000000000000001AE54A47000000000000000000000000000000000000000000000000000000001AE6F586000000000000000000000000000000000000000000000000000000001AF0E41C25000000000000000000000000000000000000000000000000000000000000000484E530C2817E087BEB4413F1A1BB9FB9E702BD37D9859195935EFF4ED3CC7AD447FF9C0FBC22DA557D0F58B62B4F4704E466348A2C8333A36CDFCD75409AE82586CCACDA03F3205E814ADABCCF0C905F37B0940E232A84E1CA7ACDB6B5B2E4132DF5B9E0AE221D7C52CF79541C49A7C1DDC545F44BA243FA3AFAD372CF67D18F0000000000000000000000000000000000000000000000000000000000000004390DB7B1D5B9428CD3919CD1DAD2595DEE256AA374EBD150466842DAAF8963AB4DB9DC301DA0DD7E8CF8A24F998591F0E1076EF72F3EBE4D7F0E4B43F27AD0225DBCBC12C20507C677BBBB4A996570CF13011D844C471CBD46BA7982EA7A0DC853AAEA45F391FAB99D8A4B6E6A4C24FA414360BB556EA4778853C0D15B9FDC5C54C782E2B9D7A0AA96E63E048071603F4319CAED81831F3C79CD1D2B082BCCAD071541A2AFCDBDDFF89A80838866ACEC83C659A746C10A578B6700016C7804E900038201EA07FF8201F5843B52DFEC831B52A7943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EE70DD2FC000000000000000000000000000000000000000000000000000000000000014000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073D9D3778B03CF3424B6E1E6E0000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000DEE5AF5E572B94B14C6B8EAD41C76119685E5DAB00000000000000000000000000000000000038A470432F7114B93BD9DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5E620F480000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10F296265FD291B3AC2C20284DF7701F05225380C591A32C684DA165C2697BBED6761F4B206CC0DCD9E9C4A5C23DA5AE9B0D8AC61F4B2E7A6EEC7C722F79F699E010382018807FF8190843B52DFEC83101CA594DA3CAD5E4F40062CECA6C1B979766BC0BAED8E3380F68FA578000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000004C9F00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000015B1BE4291B76096B912FE3B553D7A4BE201A2AB6B9DBA4B2E8E910A8EBAFFF2C65F3A458F4262CD2469F0A2BA3D0E18B8A6A98924CDBEDCE5E21A63D8F8D756D00036407FF07843B52E4BF8307425C947F5A91036A6B14BE1BF132DD54AA522EB357789A06106D237F00AC0DB02896974913F7E1DA36366A6B62E70481D1F3BC27BB65BE26611B635AE19CF1083A97FF8A62AC9267CBE21D8AD837D33E6722811D7D28501652010381EB07FF83013EC185174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E10000017C000119806014EC3F60000000000000000000000000000000000000000000000000000000062A8165400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007D722695842308C777430892E2FD71A68072B9716416DF25D328C2F2FC0E63A75CDA1C3085041AC9BB2053C4073073CEA7D016F9FED4A9DCE3823A62051EEBC0A646010382040B07FF830105E085E8D4A51000836ACFC094EFC5061B7A8AEF31F789F1BA5B3B8256674F2B7180C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000E193445CE0BAE19053668642A3CB19770000F45D0608040003010607050902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000001563FB63000000000000000000000000000000000000000000000000000000001563FB630000000000000000000000000000000000000000000000000000000015721CC00000000000000000000000000000000000000000000000000000000015721CC0000000000000000000000000000000000000000000000000000000001576B0A000000000000000000000000000000000000000000000000000000000157ADD6D00000000000000000000000000000000000000000000000000000000157ADD6D00000000000000000000000000000000000000000000000000000000157BD5DA00000000000000000000000000000000000000000000000000000000157BD5DA00000000000000000000000000000000000000000000000000000000158E6CDE0000000000000000000000000000000000000000000000000000000000000004BFDA4E56D7291103DB00A91A6ECE55C4664B5503F19DF0D1A2F17CB907EFDC99C9B27907C491FEE276C7C31D7D1D6F99C681BA897B2996C76426D8602CE3691DCAF96898ABBFE563695DE71490529ECFDD737E3A5BA693CBAB75606D4FE957038E51BB09E659848AFB03F242AF7C64359C0C100573B016A01D7D8C3A4137021B000000000000000000000000000000000000000000000000000000000000000445F102FD7555EC4654333921DDCDEFCE210275B97E7941405E8A7595CCBC178363835B7EBC3F7FACD715A80A8AAD2CCF86ACDFB8E15C903F517BBB5C50A69E0449BB76D3B57F6EBB725C0139963E02F10D0D555E9751BC7CCDD83693C648A6164BE20D10B36CE040609C25EAECE5D52C3F28B89F3F36170B08DF33F6F1C9959A35670BF1DF5F1A8C0AF174EA235DB882E5E45C8BBED9F9F813F93DC70779EC0E63B786C5271DFC7F1D5C9A3358B0AEBA22E3D5F30CD92A473C541D3B768E393C00038201C907FF81BD843B52DFEC831AA8B2943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EC9874170000000000000000000000000000000000000000000000000000000000000012000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000005F5E100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030D0CE717F80057C41BB8739C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038507FA93D563375DA6BBC0000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8C2D7F2A21827DD81C7FBF677A4FD9B5008FFEB7A40FB0908537F48D1DD8E35514AB48A158E911C2E15DE750A940634E95FBE037889C5E5EB51B23CFBAE8867FE0003818907FF820132843B52DFEC83094083945A39174E7F2B669A51EC179EF49B3ECA7DDB96AB807CB64759838184A0F907C9CCC80328FBFB5C87C47186DF8C8188DB40B54C8A52E6730EC1DDDA0D0B4BA5E1DF5C566DF96E6A957BD0DDC7C2AEC5EB7C81F5B29AC6DF557F6977DC66BA85B8C7CAEBDD404FB7CD2368E949810E466173D53885FDDA9FCA0A01038201EA07FF820197843B52DFEC831D2096943D6BA331E3D9702C5E8A8D254E5D8A285F223ABA020EC9874170000000000000000000000000000000000000000000000000000000000000012000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000023C34600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000149062E9A17587215056AAB953000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000038FBB3F4811F98508F25E40000000000000000000000000000000000000000000000000000000000B5E620F4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1BE5B60EAAFD45F9C5ABEB4590BDE928EAFAA669DC1278DA7B783BF1DD507391D34C0A243ADFA82BD4C078A5A9BF5B2949A7F360AA7F2BB02D739A3CE07E57858010382018E07FF01843B52DFEC83135BBB941B02DA8CB0D097EB8D57A175B88C7D8B4799750686D07F746DF09000FB3BDB410000000000000000000000000000000000000000000000000DE0B6B3A76400000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000B7247DF036BCECC3F4EB76ADA035E8CA5A531E100000000000000000000000000000000000000000000000000000000062A81D23000000000000000000000000000000000000000000000000000000000000000400000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000017FC002B466EEC40DAE837FC4BE5C67993DDBD6F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000539BDE0D7DBD336B79148AA742883198BBF603425E87037C0E4574144F4B02621B49EA5329269A4C6DA3EBD0572DB5ADD2112FA605DF09D1036BDD7FEE7D54C0C1483ED4499E42CC06144476F1C76C3F362B8CF4010381EB07FF83013EC285174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E17000017BF0011952C014EF9E80000000000000000000000000000000000000000000000000000000062A8165B000000000000000000000000000000000000000000000000000000000000C57D0000000000000000000000000000000000000000000000000000000000000000A27BA8FD36486D0F5D66DD07BAFBC2B204BD2E8321EB1A06232CD65C18FDCADA39413AA9814AB78EF15A3F20106DFA098DD66B415D2B69E0FD4F42B57B9FCA8D010381EB07FF83013EC385174876E800834C4B40941A0AD27350CCCD6F7F168E052100B4960EFDB774801389A3CC0000000000000000000000000000000000000E17000017BF0011984C014ED44A0000000000000000000000000000000000000000000000000000000062A8165D000000000000000000000000000000000000000000000000000000000000C57E0000000000000000000000000000000000000000000000000000000000000000B5C25E92FB23389B370B7B0D5BD0762C482A923B683200448CCEA09CD054AAF74D212F05327D47BEA3D103735A46451CE6EBB7EE4C10C7A217086CBC248BDC0F0003818707FF34843B52DFEC8307AD3C941A5261041E9340579F58401389D6DEE185B6280480E7C6133B0000000000000000000000000000000000000000000000000000000000000AA752690DC083EEA7137B1171890835A04D1806ADCB5604A3A656012254516AD885485A6B356CE2871BAE383D65003F33A03D03626CEA5EBA4FDEE11FA9F117974C010382040B07FF830105E185E8D4A51000836ACFC094F6BACC7750C23A34B996A355A6E78B17FC4BAEDC80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000005536D8DCDB0A6075552F4E5CDA6480B1000003490506020908070503040001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000013DF50000000000000000000000000000000000000000000000000000000000013DF50000000000000000000000000000000000000000000000000000000000013DF50000000000000000000000000000000000000000000000000000000000013DF50000000000000000000000000000000000000000000000000000000000013EF20000000000000000000000000000000000000000000000000000000000013F290000000000000000000000000000000000000000000000000000000000013F290000000000000000000000000000000000000000000000000000000000013FCA0000000000000000000000000000000000000000000000000000000000013FCA0000000000000000000000000000000000000000000000000000000000013FCA00000000000000000000000000000000000000000000000000000000000000040E8417F7E2765EAA22C18A6144A62067BCC87B078FE368C3E79E648935B63EAB0909153232F6E807482EA3A9C81461683C9E90D99B4E21248134363C6C2560F17B0476C7ADAE64FA59A3A8AF92308AD12893B2D03EC77CB3489740FB27ECB1180546D6DA5615C73C43FAA02D3314F84AF3CB1AE0E600855EB90E65DD11EB82AA0000000000000000000000000000000000000000000000000000000000000004082E8C91E4F6E6F3D2534CE61B791405878CB6D0C128389513870C2811EC91087F78A24FCEDF286C8A01AFE5109130B36596CF83CA2DCD34E62BB81C0BEA32FB18FDB3AF9C02B0F8C68A444D0CF3813253AF2449AAE61DF25D2B6E60A165B6491151BD8082A6D26581D06622941444A76DD1FEDB52729C9AD74F2D80CF1D2FD7567A6197CCEA7396EBD7B53692157161E1C20DD818885880C4FCCDFFF599F51004121D05C35D6159790C431EA71B4CC7D4071CB05A022692C42B0531373A9CA700036D07FF13843B9ACA008307A12094A60113F7D43130919802B0863ABDCDB956664FD58918661CCE2A166BEEB800E8F203BD888931986C12E98E27BE6AC70A15C3AC56A96FA56E646A427C60A00C652DEA50290BB5CA900F7A35B21AF304A836A8332CED765C074C49D9CF4D61BF010382014807FF0E843B52DFEC831043E8941B02DA8CB0D097EB8D57A175B88C7D8B47997506020F7FF36AB50000000000000000000000000000000000000000000000077FCED7F58EB6BA120000000000000000000000000000000000000000000000000000000000000080000000000000000000000000156548113552BB52AE921A0B44794A6A5F588C9C0000000000000000000000000000000000000000000000000000000062A81D23000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000B41BD4C99DA73510D9E081C5FADBE7A27AC1F81407D0933B12E4CB71FC44B829DC2A325E6B6B68D009DF3192488ED5E297F5710B223EDAD49E4A2939C0630110C6CD9ECD110C4DDE120B30FDFB55F739A9EB22AE000382056707FF09843B52DFEC831D6646943B6067D4CAA8A14C63FDBE6318F27A0BBC9F9237807617B389000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE000000000000000000000000000000000000000000000000000000000077A3A80000000000000000000000000000000000000000000000000017CAFA8C84DACE000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000002E00000000000000000000000000000000000000000000000000000000062A81AF3000000000000000000000000000000000000000000000000000000000000000300000000000000000000000017EBC315760BB47384224A5F3BF829222FBD3AA7000000000000000000000000003B18357460E789E711849749A793C430D14F9700000000000000000000000017EBC315760BB47384224A5F3BF829222FBD3AA70000000000000000000000000000000000000000000000000000000000000003000000000000000000000000BDEE369ABF5C3DFFF5DC65841E939747BA706A5D00000000000000000000000046C47C8DAABCA3E15BF238CDA365894046BAFA23000000000000000000000000692A0B300366D1042679397E40F3D2CB4B8F7D300000000000000000000000000000000000000000000000000000000000000004000000000000000000000000BDEE369ABF5C3DFFF5DC65841E939747BA706A5D000000000000000000000000003B18357460E789E711849749A793C430D14F97000000000000000000000000692A0B300366D1042679397E40F3D2CB4B8F7D300000000000000000000000003B6067D4CAA8A14C63FDBE6318F27A0BBC9F92370000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000C000000000000000000000000000000000000000000000000000000000000001A00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001E000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F000000000000000000000000DA10009CBD5D07DD0CECC66161FC93D7C9000DA10000000000000000000000000000000000000000000000000000000000000BB80000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001E000000000000000000000000000000000000000000000000000000000000271006691BD35E48DE925F44FBE913DC27FA40637A045BF25BDB9D39B34EF239CFD726B8C798C77B238EF0EED01DA0F63811A9DB7BBA5D33A91BB37290DECC19A2AC000382062907FF82013A843B52DFEC831A20DE94737EAF14061FE68F04FF4CA8205ACF538555FCC88011EE3CF100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000004A00000000000000000000000000000000000000000000000000000000000000819000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000081A00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000047D00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000007FB5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000068E933BA10D285279DCA376D981253530351CF02F3AF9C4A4DEA0E619F647147F25FF7D247998AEF18C38988EB602F815569C4418366E1486EBB6FC6091DB6B761010382040B07FF830102C485E8D4A51000836ACFC094942D00008D658DBB40745BBEC89A93C253F9B88280C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000C53BF610EB015FA9F4FAB204B58622E600003E7D0306090805010002030407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000001FE5456FCD7000000000000000000000000000000000000000000000000000001FE6F434300000000000000000000000000000000000000000000000000000001FEA79E7260000000000000000000000000000000000000000000000000000001FEA79E7260000000000000000000000000000000000000000000000000000001FEF76705EA000000000000000000000000000000000000000000000000000001FEF76705EA000000000000000000000000000000000000000000000000000001FEF76705EA000000000000000000000000000000000000000000000000000001FEFBA1B5C0000000000000000000000000000000000000000000000000000001FF6492221F000000000000000000000000000000000000000000000000000001FF7187984000000000000000000000000000000000000000000000000000000000000000046DDB863736D1630200BC8B20DC5C10B2E6FB5211FFCA5D82CF788FF82751D9747AA94408BBC0606BE1CE5DE3C666939822EF36C47DA8D15F142228EB71CED7B668FD86888AC3AAF904CD53E4E73E79A10EF98A164DFF4C53EACE889C0D6FDE48B776702F2656E5C26A1A22CC3C52092E091983E82590A390688F71D315958E7B0000000000000000000000000000000000000000000000000000000000000004752EA1676E1EA13E317B02FDEB2583EBFD3D0D350127C4FC65FCDF21E10043A8729D3D6D4217EC790F8E69DB67312CBE95DFE5A3712C5D9F5789397B32CF57773013C036BC0DF87B41F36D9F69D746630E324C3505F64E0213BD0EF93B2F0F1E0F188C9808ACEA5636B4B6F53D3871B287C4AA330FFE4080D39008E02A81AB47BDB91D746A80A1F5CF82E97620D017C3ABD16B5E4FA4BB68E528C067B114546E0BA2BDFD54F44ECE3ED7B1DF5B2E362B5CD0D7818017A7894FC8C3A8D9918106010382040B07FF83011A1B85E8D4A51000836ACFC0944B3F43E086790A71270750192472FB61DF7E856680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000038146A5052627722CDDF213E33323FE0001BCED0606020807030509040001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000013DF50000000000000000000000000000000000000000000000000000000000013DF50000000000000000000000000000000000000000000000000000000000013DF50000000000000000000000000000000000000000000000000000000000013F290000000000000000000000000000000000000000000000000000000000013F290000000000000000000000000000000000000000000000000000000000013F290000000000000000000000000000000000000000000000000000000000013F290000000000000000000000000000000000000000000000000000000000013FCA0000000000000000000000000000000000000000000000000000000000013FCA0000000000000000000000000000000000000000000000000000000000013FCA00000000000000000000000000000000000000000000000000000000000000045B47BE2E4CB8AB2EC2CA417F626CEC5B37B3A95E4E11DEDFD094B40465BBB5CC0F3D2D9D95359C5067186907AB7CD1E27563F804F3A964F345FE8E32B4555D1FF4CEA4EA2CBF87F3F61A699A1BE885F9B1F67D040CE8A4E2811B40C256B10AEC69FD4EF00E3B6C63950477730B07DD2C8F371259E36BEEE263407C081287098000000000000000000000000000000000000000000000000000000000000000042F74C247976A7B263F01FFEB652C5F19BDB45FF4D908F92679732CE76132D4E51B058282795F347A3E80652F622965D22187B69E0A7EC6C4B32217AEA2B47C7D3C8D9A6D3B3F7E53C4E7AAEEA72AD334DDB7900D520B008FA3044B15A2609B2D5A2D92BAEAD7A9A1AB9E1C0B06F5CE5265620B6125CC857E8F9CAD117F66988121FC10EA018E494958EB373B7142FFE6C7B383F35A61EFF28D6EB4E6B22CC8BB1EF0064F6BAFE90D07B533EC506EF34401EC2C035C259D0F7682A0614882C7B5000382040B07FF8301097D85E8D4A51000836ACFC094FC06BB03A9E1D8033F87EA6A682CBD65477A43B980C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000075CC6B84F2B1017D74A4140F3CAE1ACF00010C810406070200030409010508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000005F69CA80000000000000000000000000000000000000000000000000000000005F6A6120000000000000000000000000000000000000000000000000000000005F8A1FC0000000000000000000000000000000000000000000000000000000005F8A1FC0000000000000000000000000000000000000000000000000000000005F8F7500000000000000000000000000000000000000000000000000000000005F8F7500000000000000000000000000000000000000000000000000000000005F8F7500000000000000000000000000000000000000000000000000000000005F950C90000000000000000000000000000000000000000000000000000000005FABE250000000000000000000000000000000000000000000000000000000005FABE250000000000000000000000000000000000000000000000000000000000000004FDF013712D8CEB64BE4896F37F7827BC1584DFA397DD48CB869C3795CE018645ECFB3D6E46F583C32B184678D54023AA8887BAD1DFAF372555F61D6272166735E8852949AE495D5B48A48D95372F71549B54E45ECFDFD5B52FA05712767DF687A55A938492433B625F12D368ADFD9792945B5F501A9E3CE315BFD48F2D031B6900000000000000000000000000000000000000000000000000000000000000044D71F8E4A5D8583E3DB8099B661819C4053CEC02458C65B149CDEE9C44DDC9C96B142FBB55F473D6DE168739816D54ABB2AA1C3853D5C8627B05EE001C900C4279D918F754F9AC9D0FD1464AAAF179751348C3042A54CBAEA9C4ADAA801B4D710342D0E46E12DC4411FF7EF89E3D7001CC57A49A8C286BEA6B0C5E9199E91882EFE57B2C32AC0DE57AB4D00167D1876053F3110C599A51EA24D1DDC6EA5F850D1E1FFEF935A2A2D4DC466FF54E9071658D85925DB682D93EF9F680B17E1E4D300003818707FF35843B52DFEC8307AD3C941A5261041E9340579F58401389D6DEE185B6280480E7C6133B00000000000000000000000000000000000000000000000000000000000024DBF7C495E36E33F0586937B42E1F292C27B178242233916F7CE4C7FEE7E6C7A69648D6BC5B5A357A458C3F3904FF2DF35A85CB235344D7B66B095CE7BDEB6D6DF9000381E907FF8204EC843B52DFEC831240729479A556EF2C5B613DB3DFA8797E6772C5AAF8683480D6F5195D00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000036020599B2020000EE020002E6030000000004A817C8000000000004A9C0543F04040302059A3102059A7B02059A7802010732020000EE0000000000000000000094162BA1968826B0A514FDB79B42F6806E1B0B170855AA0C9E81CDCAC29827820BFEDF1B277E498BBB77F0A90CFC9DCCD0028309ECEEAEEF188B34EB95C91CB901038205EB07FF17843B52DFEC831D8550941111111254FB6C44BAC0BED2854E76F90643097D807C02520000000000000000000000000026271DFDDBD250014F87F0F302C099D5A798BAB100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000026271DFDDBD250014F87F0F302C099D5A798BAB10000000000000000000000000C4CA96D4E63AF64FB7896AB41E0AA871A59FABB0000000000000000000000000000000000000000000000000000000002D0FC420000000000000000000000000000000000000000000000000000000002CAD98700000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064EB5625D9000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000BA12222222228D8BA445958A75A0704D566BF2C80000000000000000000000000000000000000000000000000000000002D0FC4200000000000000000000000000000000000000000000000000000000800000000000000000000000BA12222222228D8BA445958A75A0704D566BF2C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001C452BBBE2900000000000000000000000000000000000000000000000000000000000000E000000000000000000000000026271DFDDBD250014F87F0F302C099D5A798BAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111254FB6C44BAC0BED2854E76F90643097D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000062A967DE5A5884FC31948D59DF2AECCCA143DE900D49E1A300000000000000000000006F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB90000000000000000000000000000000000000000000000000000000002D0FC4200000000000000000000000000000000000000000000000000000000000000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E26B9977E2EE8C7A4D84E12AD5D2099B97B421A0923295C0B94EB6E9EC51B2221AC418A329A51CC2B285D1B4D31CC6BEA1354970570F041204C8D8F22CBE36315045F901000382016807FF0B843B52DFEC83110B9A941B02DA8CB0D097EB8D57A175B88C7D8B47997506010E7FF36AB5000000000000000000000000000000000000000000000000000000000001C36E00000000000000000000000000000000000000000000000000000000000000800000000000000000000000002C191F237A9282844A837F294FF4358FEE1047470000000000000000000000000000000000000000000000000000000062A81D23000000000000000000000000000000000000000000000000000000000000000300000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000017FC002B466EEC40DAE837FC4BE5C67993DDBD6F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8510847B63E3BB5CE80F8D8A3BC96DDACBBF76A1325F267E5FA04E2696E2C345C3823827C35C406F88DAEC33A1C900385EB519552C6FCFC72D486D60A27B2DBF5010382012907FF820FCE843B52DFEC830DB54D94F7C86A5E1323E6EFB954B2E65EBBA9C300C40F38804D11B0F10000008CFBAF0000000000006FF7618B00000000000062A82B3C03C60123290122FDBC81D31509D4AAFD5011FC84D7C7BE6011138AC9DE0F62F6B6F8C5364B1E54643197DF4B5D1243D35D0CF61072CBE7FD1E0DE86F6D6F37375326055DA12F000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000001A55A5AAA3B462E8273BEE6BD813FEA4744F651A0000000000000000000000000000000000000000000000000000000000000001B135AFF68ACD4A22A578B1CBE676DEBBDF61771286FB5C44F643DD4858A8276617E5EE4DC06DD877F876860F69CB73C22702658B412DF579D492924741C39B3A000381A707FF13843B9ACA00830DB4AD94DA10009CBD5D07DD0CECC66161FC93D7C9000DA180095EA7B30000000000000000000000003D685292905961E7C5C1CB9327A51314D283874DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC4A9AF80042A922BD3953EECC442766F4C2C96A89D566B61041675419E2596347D3E08E1F406FF749B65E487B1FC53AFFBD4D37C4702777E81DB89706067D14000382018707FF34843B52DFEC831014C394DA3CAD5E4F40062CECA6C1B979766BC0BAED8E3380F68FA578000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000006F45000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000132F44F5F15DF6F6F1C91EAB657B68642908F9FF5A1086B26127876AB7B4D1A8440D9EB7DE03ABAB4E4943559A99E3802367CB8AE20A3F8403BDF8A457D0A363C000382040B07FF83010AF585E8D4A51000836ACFC0943607E46698D218B3A5CAE44BF381475C0A5E2CA780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000F6D9397093865A569A3B827FBE021B4E00016AF50107030009040208010605000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000001ACE5078D00000000000000000000000000000000000000000000000000000001ACFC5DAC00000000000000000000000000000000000000000000000000000001ACFE45F400000000000000000000000000000000000000000000000000000001AD29304800000000000000000000000000000000000000000000000000000001AD4C797C00000000000000000000000000000000000000000000000000000001AD77671E40000000000000000000000000000000000000000000000000000001ADB8820250000000000000000000000000000000000000000000000000000001AE6F586000000000000000000000000000000000000000000000000000000001AEC6BDA750000000000000000000000000000000000000000000000000000001AEDA65C530000000000000000000000000000000000000000000000000000000000000004CADC07C399C99EDC0A2999BB95C9E93B8748327F5379AAAD552E87E2527EB9CE91C12843547657105874E6387B50DDD53E0980FCB6AEF816A71EC4104AC4D53FF2D34B31ACB188631395F6F27423A03C715C8BFCC6A03EFDE563953E2DD20D1AA6BB4414248A011E04D85E35090F6FF748F40C8FFF71A4DEB3B48647A63A366100000000000000000000000000000000000000000000000000000000000000043A6D0F895F733D3FC7DC2C81FC6278328966DE134985C9A2337930A69FDE9FA038DA516E3B77C9404124AD354557F44EE95EE7F32D80A165BBA53DEFA1D156562F351D9A3F8905CA5312F1CD48C20B8C7F52FC5AE439686368F0900998303F534BB840E2B9062E656A8473FE4320957FFFA6CBF86DF7C2B09CABFC75A9E785FE7795A4D75FFD252D61FF756D9E2D1188F932E741EB41AF3980F625D5E7462FB82529530A29486287C169EAA8294FEDD217EC43C4CE58A30D1AE662C29774740D00038201A907FF821001843B52DFEC830F175194F315A5CC91338A3886D3C3A11E7B494F3302B3FA80C6AE83FF00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000005A0CC43979CDACB700000000000000000000000000000000000000000000000000000000000000E00FFEEC83EDFDE69E401DCE2A909B41DFF1902AB1033B9FAC150401091253EB8000A2ADD370EBB81F03E0FAFECF021A0041DFFE64CFBDDCFC20960000BBF7B1000040FF26A9EE7DCF3B8BEAEB297F5EAFB90D0401E921F0028D86C040EF24CBC0FEA6EEB7FAFF80007FFF8E3EB0131BC6026F93F0FF7F0E18009675F8933D0640C436BE522CE0221FB026CCBF987C15AC40B03F1BFFB2FD081FF1F26DFF90FE4000BAD012B20A3B1C9B5E05625EDB85E17F48C81398A98027BB00000BC21E0000FF81600812FEFFF9A01BF3C25FD6B1F871EC9C10C87AF03FFE0038A070000000151A87357C14B1A76A3727A02363113BB39AAA606B4A5418F92ED84914A4356504FEEE0825C3BDF1ECE1C18874B0925D392FDFCDCE4EEA71250DB437664A1A01000382020907FF820192843B52DFEC830F063694011AFB2FD1F67E7FD8F2A7D926245019ED93A900807C2CB0AB00000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004FA0000000000000000000000000000000000000000000000000000000000000001C44BF889D1744D1C8A763E8B1A65836AA6CF032D29CB8733EE752BF960753E2A000000000000000000000000000000000000000000000000000000000000004107540A06CCF264702FAF003F4A1884C13A010F16B449266CEFAB8B07B7FA48F1327297E57246C176E402781419E0CAA63415F7858425025F27E1D773CB21FDF91C000000000000000000000000000000000000000000000000000000000000007CE5AD6CFE7C1A865D485862C84259BD1F5275D106625E0463C7A744FD6A4B03161B45B3DF9721136843874CC588F3C1D0FD03482A9D67381E61CC2118971633010381C907FF820386843B52DFEC8309F689943E455C3321EF4861DD8492D7FC099190A846458A802B66FDEA0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000EA0D4E169F26402FE9E62E87C657BA003AA400BDE403751E0DEC5E0FA4D331C6EE038FDFD7400C12FD2748CF515A87930CCDE4AD8AE444EF9915C0A0F7BE7E6C95000382018707FF23843B52DFEC8310A293941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED1739000000000000000000000000000000000000000000000000000000009ACB134000000000000000000000000000000000000000000000000AD79F3A3E52062AC700000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000E1929D6F170B2FB5D0FF78E92A8F505F7C16D0900000000000000000000000000000000000000000000000000000000062A81D230000000000000000000000000000000000000000000000000000000000000003000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000032EB7902D4134BF98A28B963D26DE779AF92A212D89A0DA0D37AD99A662BC237ECE7F3FC2DD929A04FE8B2EDE26B5B44723EACB9780973B663A53B0D9374DEC89713C36140A88269FE796BB41CC5971CE3909AB900036807FF03843B52DFEC8307819C9488374B3A8BD236EA9BEDBFE14987B9E02A7BA0BC84017B82A20ABAE344FFB9CEBE93A1617CC2021B2C32E013ACF37AA333FF7E0415559A2DD3B239726684683A98A5FCEA30147234FB659BB2BD51EE4A65F0B47D2727CA47E8A4000381A707FF01843B52DFEC8309EA0094FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000ABBC5F99639C9B6BCB58544DDF04EFA6802F4064FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC96B4F10E29432C85C5F9575D860A17694FFB430340A1D1500BFB4204695B9812240F356CF6C90823DEC7A3ED9BC7C83B56595A9DE86738E1E0E5AAA8B092ABB000382018807FF0B843B52DFEC83142042941B02DA8CB0D097EB8D57A175B88C7D8B47997506010E7FF36AB50000000000000000000000000000000000000000000000000198D5D93C0C77C00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000C654CB0DE4C33A78C571DFA57B78022E95E3A8ED0000000000000000000000000000000000000000000000000000000062A81D23000000000000000000000000000000000000000000000000000000000000000400000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000017FC002B466EEC40DAE837FC4BE5C67993DDBD6F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000DA10009CBD5D07DD0CECC66161FC93D7C9000DA1E4DE260AD237C622BEDB1B0638F343AFA395AAC09CF524576048279F2469EE1C01C560D1A0F308FA9A4115842395E9C2D8B1BA0F3ADC46592FCEAF33650B44930103818707FF36843B52DFEC8307AD36941A5261041E9340579F58401389D6DEE185B6280480E7C6133B00000000000000000000000000000000000000000000000000000000000024DD6B8E05BFCC98C56B0C494C049504422D64ED3755657F4609EBEA223B6015BFC8440F5206E4C7CE01A67DF3A6627A6E8FD6DD0BE57D34622B95B69F4161529AB5000381C707FF20843B52DFEC83091D2B94DA3CAD5E4F40062CECA6C1B979766BC0BAED8E3380F93309D10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000072A0C81BE001C2B0CD549AD91B648281D334CFFE8D873C19775DB2038F59BB41219424DDC966ADEA36652AE0BC61B44944A8AFC458D7CC47035E4C95E795406611D7010381C907FF821A858447303FE883124F8094A96B576F3F117158176E396467D591A1F5DBA9DF80B8F8BAD4000000000000000000000000000000000000000000000000000000000000000B00000000000000000000000000000000000000000000000000000002540BE400000000000000000000000000000000000000000000000000000000012FB87723D6907C00C3EEE3C7946FC0888187C9AD2C919DB0066117E10EFD4B440BE6D039584AE6B9718800742B07FB0551973BE668689E9FEE6DEDE4C115374FA48939C0000381A707FF03843B52DFEC8311E0FB94A0A89DB1C899C49F98E6326B764BAFCF167FC2CE80654CFDFF00000000000000000000000000000000000000000000000796E3EA3F8AB000000000000000000000000000000000000000000000000000000000000000000004EE37CE11AF1081DE1EDDFF3D84EDBDFD38ECA4560E594BD4C5461F105A18EBA876A8A3F851FDE704E5C414B5F98E1A65FB4415E0B8F1D92EB1F5ACAD7603E1D9010382032907FF822C5C843B5312A08315693A949EEA8E424CA2E03BEF5EEE46668D5D98EA0EAAA78049B42C9E0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000055D64760000000000000000000000000000000000000000000000000112E0E571E89CAB0000000000000000000000005481484616FD5BCC97DD5BBB4F58DAADF34D099D0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000530476D5583724A89C8841EB6DA76E7AF4C0F17E000000000000000000000000403B1405D8CAFFC1CC5032CC82AA135D2481D0CF000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005F5E10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026F70000000000000000000000000000000000000000000000000000000000000000B6163875258656BFECA65974862A700A2E0C1DA4FD7C77584F14D0F5AA55455B083A0405D277FBB69B2B0B2FDE38B83E19230E19D1C73225AC848841D0A03010010382048707FF08843B52DFEC835374B99428FEAC06DC72188B385478B507F7C7A39A7026D5809B4A89CE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003C0000000000000000000000000000000000000000000000000000000000000027B5765656B206F6620362D372D32303232202F20362D31332D323032323A200A41737369676E6D656E74733A0A312E2045646974696E67202F20616D656E64696E67202F206D657267696E67206F662053656E7469656E74204C6177204772756E742046756E64204C4C43204F412026204B616C6944414F2052696361726469616E20536572696573204C4C43204F41206C616E67756167652E2041727469636C657320312D352039302520636F6D706C6574652E20546F74616C204F4120726F7567686C792037302520636F6D706C6574652E20486F75727320776F726B65643A2032320A4472616674696E6720616E642065646974696E672F7265766973696F6E206F6620224C6567616C20426173697320666F722047726164756174696F6E204576656E742220666F722052757373656C6C20284B616C6944414F292E20486F75727320776F726B65643A2034200A4472616674696E6720616E642065646974696E672F7265766973696F6E206F6620506172616469676D2044414F204D6174726978205375626D697373696F6E2E20486F75727320776F726B65643A20340A4D697363656C6C616E656F7573206C6567616C207265736561726368207065727461696E696E6720746F207377656174206571756974792C2077617272616E74732C2044656C6177617265204C4C43206C61772C204665646572616C204952532054617820636F64652C204665646572616C2053656375726974696573206C6177732E20486F75727320776F726B65643A20360A0A546F74616C20486F75727320776F726B65643A2033360A50726F706F73616C20746F2074726561742061732066756C6C2074696D6520636F6D702E0A0A4B796C6572205700000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000D00E5109A8B25CEC2B6F5982646DE18ABEAF73B1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000010F0CF064DD592000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000002487AE3B28238AAD0D5108839B211F25207B7FC0D0802C8772A05720F440CF68763369341C561E53F90BC4A80E6626C7A7BF8E43F9575C9C406E7E5063F0C3FE000382046707FF14843B9ACA008332282494E8C97BF6D084880DE38AEC1A56D97ED9FDFA0C9B8006E75722000000000000000000000000DA10009CBD5D07DD0CECC66161FC93D7C9000DA1000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE000000000000000000000000000000000000000000000010AD32F3464B51F34B00000000000000000000000000000000000000000000000000000000000000C000000000000000000000000000000000000000000000000003A9948FCC2884E00000000000000000000000003787F7A251FA6D80FFBFE5ED13DB52152BEFF6310000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001800000000000000000000000008E8ABDF5DC296057E7920759EB8829303F537718000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000C44FCFECD1000000000000000000000000000000000000000000000010AD32F3464B520000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000DA10009CBD5D07DD0CECC66161FC93D7C9000DA1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000000000000000000000000660DE0023DFE38059138DF60F3EAEAD87771BB9F00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000124EF5DAB3A000000000000000000000000000000000000000000000000000000001253AFDC000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001F40000000000000000000000000000000000000000000000000000000005C75D0EA1B29DF1175DEDB29B2118939936E12AC2A7810F388D01C130FAD79F0F154F9322406603E6174BCDF1366AE629A06347B19F576080B1BA458A09B7EC010381C807FF81F9843B52DFEC830915B294492F6BF5BB7B72B5B4023503522A063FF453B00F80C79D54F300000000000000000000000000000000000000000000000000000000000022060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A9D39B605A78C809656CF00CC10D23306A7DACAB7A93976FB35D76F7B1B1CA8315D1D58BE0CA23840757906066B8C6F409CC97BC29BCB0AEEAC485663828323BD000382040B07FF830105E285E8D4A51000836ACFC0940050D50CECC09CE311D4E0AB14377BFCD0397AF780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000009E69D7EE25C4BBBBB119859635E1884300002FB40207080605010009040203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000001716000000000000000000000000000000000000000000000000000000000000171C0000000000000000000000000000000000000000000000000000000000001724000000000000000000000000000000000000000000000000000000000000172400000000000000000000000000000000000000000000000000000000000017240000000000000000000000000000000000000000000000000000000000001728000000000000000000000000000000000000000000000000000000000000173200000000000000000000000000000000000000000000000000000000000017320000000000000000000000000000000000000000000000000000000000001734000000000000000000000000000000000000000000000000000000000000173C0000000000000000000000000000000000000000000000000000000000000004991DEA948043B26F27CC2B817F90A0E0BA021F35532ED4199ED49D045F3FDE56AEBC2C771D0A49255A8ECA6F548F02484F418443BBDB7A1675C4A800B11E8C1B2B325232D335C8E4689B37D243BB6EB6069BA66985C863A7C8024B243817CA286F0EDA103FC8667CCE9FB8A26CC04F43EEFEF4024CC11629908EC952B521FC85000000000000000000000000000000000000000000000000000000000000000408B272409CB2DB6727B146A485A913574B65A18946BF1B64E1629536B072681C7BC9380CAD566237C50550CB2AE437B7CE1A1D6A4995B5BB22445DBC811051E873223D2417C1A7FCBB56FD93D89A53F998A73D17423864C266A11A5B6E8F50680DCC88D8417A447279BC7B427C73477A1B7355EF333B8F521B3905C7463AB61053F6399311F844CCA2D1B4BE1D0402BFA5897EE4E2BC323E16DE136D9989E7054B16147CB2A716657AE5354561F41D5F88760602264869AE587E4840C4A212B6010381C907FF821A868447303FE883124F8094A96B576F3F117158176E396467D591A1F5DBA9DF80B8F8BAD40000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000037E5FC0000000000000000000000000000000000000000000000000000000FF72920E351374340446E038AF3077DCBCC502D21794D26891087DF6F8A07978B2498705A23F3C47662E0771EDDA9903299DD2B7E9B75E3EE0FCFF328426C44626EF4FBB5010381A707FF08843B52E4BF830A32EC94FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880A9059CBB0000000000000000000000007F5A91036A6B14BE1BF132DD54AA522EB357789A0000000000000000000000000000000000000000000000000000000008F0D180CB40DD50723B10EAF5B4A1FFEBB53DDB02F7ED6BEF12328969811C20C80018C21FEABF7FD006E77795B27EB7049B2B3AACD8377C7665144FF71A8EE1268956AD010382040B07FF83010AF685E8D4A51000836ACFC094942D00008D658DBB40745BBEC89A93C253F9B88280C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000C53BF610EB015FA9F4FAB204B58622E600003E7D0406090403080501000207000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000001FE5456FCD7000000000000000000000000000000000000000000000000000001FE6F434300000000000000000000000000000000000000000000000000000001FE79D061AB000000000000000000000000000000000000000000000000000001FE895E9C80000000000000000000000000000000000000000000000000000001FE8AE0A8A0000000000000000000000000000000000000000000000000000001FE8AE0A8A0000000000000000000000000000000000000000000000000000001FEF76705EA000000000000000000000000000000000000000000000000000001FEF76705EA000000000000000000000000000000000000000000000000000001FF07506EC0000000000000000000000000000000000000000000000000000001FF3E652E0B000000000000000000000000000000000000000000000000000000000000000410274331CD03B17D1B6358CBF1B33A605C941DF8518ACC374672D8856F840A57C47DD184BAA041C7B7822B4E92D0BB96C839FCECA66F8AF73BA9616AB0971917C1348F0C0D9E70CEF05194D4C7638016BC36D7F230D539B70B4ADD0159E026CF22856DA926CABC9DA39E889C84CC5215D3C2006FD4E17A2A62C0DC34F4078C9B00000000000000000000000000000000000000000000000000000000000000042B61410DEFF84EF838EA7C16FD41C092C54239E09FEE7400204286A447FA5F0570D6C1DA9AB1A23771BE44E170DE9E5358BDEEDE48C396AD4A2689166350A9552AD5CE6B85CA47C4961D430DB99EB6D12EF59A34F22AA329459B996E6B20DE8E46B265F019626E79EB796D1D1A79ECE419F30666025B6201AA0AF292671B6477D98C38F04E22D3D6B599A450690CC1FF9DE95ED6EA52354A7538198EC6A26C720105644978002F0B3DC0EE62EDC291E538CED963E413C3F6327A8AD2B10AC7FD010381C907FF821A878447303FE883124F8094A96B576F3F117158176E396467D591A1F5DBA9DF80B8F8BAD4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000002540BE4000000000000000000000000000000000000000000000000000000000A1606179F16E17F1F3E4A685AFAC913028FBD757A3450680E75BCD04857D874DAF2EEC6C5371FA6AC0DBD2DD64AE7B28424BA4DAE5C8609BE3D501A8F8E295C86B145411A0103818707FF37843B52DFEC8307AD52941A5261041E9340579F58401389D6DEE185B6280480E7C6133B0000000000000000000000000000000000000000000000000000000000000AA5ED7A051103A8B222A4628C247DAE438720703F7FCC7A1D549D856723649EFD20240B562FAAED7BE01D3E2D178B6A53A976BED9B7E1D43297620DE20192FF3C42010381C907FF8243A18447303FE883124F8094FE7C30860D01E28371D40434806F4A8FCDD3A09880B8F8BAD4000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000003AB17B00000000000000000000000000000000000000000000000000000011382C981EF99CC3E9E3FC189A56031901AA9AEB3E43C9BCB2A76A8E5398FD2171125DDA9F5BAD197F6FDD32F2AB660F73CBF3F4AFB0C668A4D18E449B7F2DA90D924CB690000381C907FF8243A28447303FE883124F8094FE7C30860D01E28371D40434806F4A8FCDD3A09880B8F8BAD4000000000000000000000000000000000000000000000000000000000000000B0000000000000000000000000000000000000000000000000000000271D94900000000000000000000000000000000000000000000000000000000013EE816B1C109A466A0F94B1ABEF7EC07E3C79F95B427E32F4AB9094CF5D5700500C465B210C7BEE61A71887EFC229829160B70DC2FB61927877979D7EFE32B8CDCA91229010382030707FF78843B52DFEC832CFFE4949E6EF7F75AD88D4EDB4C9925C94B769C5B0D628180331239260000000000000000000000000000000000000000000000000000000000000CD9000000000000000000000000B5E89DC549B070CDD51FC18F1072AE9EC6E7A7C200000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000347B5D2000000000000000000000000000000000000000000000000000000000347B5D3000000000000000000000000000000000000000000000000000000000347B5D4000000000000000000000000000000000000000000000000000000000347B5D5000000000000000000000000000000000000000000000000000000000347B5D600000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD90000000000000000000000000000000000000000000000000000000000000CD9000000000000000000000000000000000000000000000000000000000000004110E0BBF54EDA256CC2D4D7743C350D9B5A5E1224F958C36CB16535E274671BBB4CA864EB2CF28F9BFD85E500B2DD9D2E970F99CA4246B59B49792624D3A7912C1C00000000000000000000000000000000000000000000000000000000000000A2438EDFB8611C6D356FC0F4D415776983AD05A7B51789AB4CE9C468F78E4D5275072752B3D70AA4BDB236843D7F3E3C1C9255EDC773F4EC27003D96A897BAA0010382040B07FF830102C585E8D4A51000836ACFC0943C6ABDA21358C15601A3175D8DD66D0C572CC90480C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000B9272C57951E29E59E3027B75D9B26B700027FA50305080607020409000301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000015D0B7800000000000000000000000000000000000000000000000000000000015D29FC80000000000000000000000000000000000000000000000000000000015D800B9D000000000000000000000000000000000000000000000000000000015D800B9D000000000000000000000000000000000000000000000000000000015D800B9D000000000000000000000000000000000000000000000000000000015DB58F92000000000000000000000000000000000000000000000000000000015DC7E78D000000000000000000000000000000000000000000000000000000015DC7E78D000000000000000000000000000000000000000000000000000000015DE8B0AD000000000000000000000000000000000000000000000000000000015E0EDE4000000000000000000000000000000000000000000000000000000000000000048A9096BCA59F3AE44B5E12EBDB9D98794271D959200449D5AE92E4CF79DCB70FA422FD45C33448DE5B0FF5BF59D80758C4260D0A729E44B78CF23AE358FAD800B467C8CDF75A630C4B03B69F1ABABFABF371B50F707BEDAE2FE5C67E02F963B2696761E301C181E435A0D4986DCBDA7D6E74DBF85BB41C3EE4992A41A9CA44D80000000000000000000000000000000000000000000000000000000000000004344C2DDAF9646DFE0AEBC40C38B1C002AF4D296144CC73AC6D255CCBF5F77CF93C35541014419979516647C34A59581D6E4376F855CDFFA16E5523FF2AD15CEC1E58537ED39A82CBD56E71DEB12F74E01E1CCF2D92ADC8914695ABD80314EED448FEA080FA0E94F431F8FA6B6CE181030D50BD57085B36C5E8BF19A2FDB3763B8A565E51118BE8C9C4ED5EE5A5EC2A17CE0C3121C02D8B19B6823838C41FE10B4853978B05725A815149CFEF68EE2558CE3EEF02059B07EC22C0129DCF17FB8D010382014E07FF01843B52DFEC830F64B8941B02DA8CB0D097EB8D57A175B88C7D8B479975068668FD8B38AA3C00FB3BDB4100000000000000000000000000000000000000000000000006F05B59D3B2000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000007AC4F00A74FB9B457D02CF31E86F69505718C3D00000000000000000000000000000000000000000000000000000000062A81D67000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000539BDE0D7DBD336B79148AA742883198BBF60342065920ABE64CEDA7D52595DE1E64FE58A01BA9A7A40E781B0913DDCAA0FD7C6D2C20A6EAC2DD04096CC4030655EBB5974E6896E3ADFEEDC846623A0CA3B0CD12000381C907FF8243A38447303FE883124F8094FE7C30860D01E28371D40434806F4A8FCDD3A09880B8F8BAD400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000271D949000000000000000000000000000000000000000000000000000000000A971FFF335D3DB5C1B0F79020D6AB3BEDC30CC0F55AE54937DDAB59D62949BB4886CDB55B398D429059970B6A615EDD5D2C1E41719AD6C67AD172E35EB864D1AF8D44F237010382040A07FF82137785E8D4A51000836ACFC09455EFAFFC2764389A08FFDFCD36AEE2C30610D42C80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000B64087573E4FCAAC4BDDAD8F7FC7A39E000047C40404060205090300080107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000119F4A55F9000000000000000000000000000000000000000000000000000000119FBED30800000000000000000000000000000000000000000000000000000011A5D5150F00000000000000000000000000000000000000000000000000000011B057FB4000000000000000000000000000000000000000000000000000000011B1258D5D00000000000000000000000000000000000000000000000000000011B2A2FB5F00000000000000000000000000000000000000000000000000000011B5119D9300000000000000000000000000000000000000000000000000000011B570964A00000000000000000000000000000000000000000000000000000011B5783CC000000000000000000000000000000000000000000000000000000011B7B7A73400000000000000000000000000000000000000000000000000000000000000047252F55AECB6684057B0453F71A36A0A89AB5C73D3B2B7D30B77A3658C53C338F9E9D78C0034C8FA42D3BE114D942C61BDA24823038C5605A95FBBB53D9B754AF6CEF0393EF80D6A470A14830AE03FADE71C068D25F6F83ACA04CA0BF45970EC393E405FC553A8B54FAC988C77D01A1ABC47303F946AD9B85EF845C5A6C7942F00000000000000000000000000000000000000000000000000000000000000047F56142103310A9C678F057C7750CDD98BD2D83A78C25B4D338586BCAAAF9FFE24984EE99998B09C85986B79A2F0EB775043307F745F7D1BBBFB9F6E921C20597E99AA85A6DF2E1063BD13183BF6D477D948C42838E4DEDDC705ACC7C897BBBD6129AD85EB6B0CEE297543D3F0CA6000B01A1096E0F88CB72197FA00AFCA2759F968BADF615AE816FFD338970D5C0553F3E6C8539DFA00018147F75E520ED4817D03BEEBB4349416B0612A72391391B13A4823DA60AE83CD5FFB0AE41D8A1FFA000381E907FF8204ED843B52DFEC8310542E9479A556EF2C5B613DB3DFA8797E6772C5AAF8683480D6F5195D0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002E020599B2020002E6020000EE030000000004A9D249400000000004A8197A0604040202059A4B02059A7B020107320000000000000000000000000000000000007CF1231945623497A13B26A3267BBC384F4B6DD88B5AD01736CB4045786D9FBD6E3C0A587CA176DA2A2011371F00DD4D800E52A558EEB62A404F510613D63FC401, lengths=[1039, 0, 1039, 0, 813, 0, 170, 0, 1038, 0, 397, 0, 397, 0, 654, 0, 366, 0, 174, 0, 366, 0, 105, 0, 140, 0, 140, 0, 107, 0, 139, 0, 170, 0, 1039, 0, 526, 0, 108, 0, 492, 0, 108, 0, 174, 0, 170, 0, 718, 0, 205, 0, 238, 0, 365, 0, 1039, 0, 141, 0, 365, 0, 971, 0, 236, 0, 1547, 0, 332, 0, 110, 0, 460, 0, 236, 0, 238, 0, 1039, 0, 301, 0, 1038, 0, 237, 0, 301, 0, 494, 0, 781, 0, 628, 0, 238, 0, 170, 0, 171, 0, 587, 0, 138, 0, 461, 0, 171, 0, 170, 0, 589, 0, 492, 0, 462, 0, 238, 0, 238, 0, 238, 0, 301, 0, 104, 0, 269, 0, 204, 0, 462, 0, 269, 0, 140, 0, 335, 0, 170, 0, 238, 0, 102, 0, 102, 0, 365, 0, 237, 0, 236, 0, 1039, 0, 651, 0, 104, 0, 170, 0, 236, 0, 268, 0, 108, 0, 1038, 0, 234, 0, 1039, 0, 237, 0, 236, 0, 112, 0, 1039, 0, 1039, 0, 1039, 0, 749, 0, 170, 0, 525, 0, 237, 0, 526, 0, 718, 0, 1415, 0, 750, 0, 365, 0, 366, 0, 365, 0, 204, 0, 1039, 0, 237, 0, 750, 0, 365, 0, 337, 0, 1039, 0, 237, 0, 1039, 0, 1038, 0, 365, 0, 331, 0, 620, 0, 1039, 0, 109, 0, 170, 0, 140, 0, 1038, 0, 494, 0, 396, 0, 102, 0, 238, 0, 1039, 0, 461, 0, 140, 0, 494, 0, 402, 0, 238, 0, 238, 0, 138, 0, 1039, 0, 111, 0, 332, 0, 1387, 0, 1581, 0, 1039, 0, 1039, 0, 1039, 0, 138, 0, 236, 0, 1519, 0, 364, 0, 301, 0, 170, 0, 395, 0, 1039, 0, 429, 0, 525, 0, 204, 0, 395, 0, 106, 0, 170, 0, 396, 0, 138, 0, 202, 0, 204, 0, 170, 0, 813, 0, 1163, 0, 1131, 0, 203, 0, 1039, 0, 204, 0, 170, 0, 1039, 0, 204, 0, 138, 0, 204, 0, 204, 0, 779, 0, 1039, 0, 338, 0, 204, 0, 1038, 0, 236, 0], sectionsMetadata=[162, 14959975, 1655182831, 530447, 49960583412871569319426850906130198713021072941875493083843918501040401394982, 132, 14959979, 1655182875, 530447, 0, 62, 14959983, 1655182943, 530447, 0], afterAcc=32D481A389D93CACB8CBB3D18A141FA0C2949BE99656C23E15755E81EBB55262, gasRefunder=0x284c1875694058b213866F5F2aD015b5a4B9438b )
    • TransparentUpgradeableProxy.STATICCALL( )
      • Bridge.DELEGATECALL( )
      • TransparentUpgradeableProxy.d9dd67ab( )
        • Bridge.inboxAccs( 530446 ) => ( 6E74B028DE9AF3A3F0264B77690A8FC6A81BECA1F131DF1F729ACA0D181FAD26 )
        • GasRefunder.onGasSpent( refundee=0xa4b10ac61E79Ea1e150DF70B8dda53391928fD14, gasUsed=293305, calldataSize=96004 ) => ( success=True )
          • ETH 0.053168733356252083 Arbitrum: Sequencer.CALL( )
            addSequencerL2BatchFromOriginWithGasRefunder[SequencerInbox (ln:160)]
            File 1 of 5: TransparentUpgradeableProxy
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 { revert(0, returndatasize()) }
                        default { return(0, returndatasize()) }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overriden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./UpgradeableProxy.sol";
            /**
             * @dev This contract implements a proxy that is upgradeable by an admin.
             *
             * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
             * clashing], which can potentially be used in an attack, this contract uses the
             * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
             * things that go hand in hand:
             *
             * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
             * that call matches one of the admin functions exposed by the proxy itself.
             * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
             * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
             * "admin cannot fallback to proxy target".
             *
             * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
             * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
             * to sudden errors when trying to call a function from the proxy implementation.
             *
             * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
             * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
             */
            contract TransparentUpgradeableProxy is UpgradeableProxy {
                /**
                 * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
                 * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
                 */
                constructor(address _logic, address admin_, bytes memory _data) public payable UpgradeableProxy(_logic, _data) {
                    assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
                    _setAdmin(admin_);
                }
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
                 */
                modifier ifAdmin() {
                    if (msg.sender == _admin()) {
                        _;
                    } else {
                        _fallback();
                    }
                }
                /**
                 * @dev Returns the current admin.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
                 */
                function admin() external ifAdmin returns (address admin_) {
                    admin_ = _admin();
                }
                /**
                 * @dev Returns the current implementation.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
                 */
                function implementation() external ifAdmin returns (address implementation_) {
                    implementation_ = _implementation();
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
                 */
                function changeAdmin(address newAdmin) external virtual ifAdmin {
                    require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address");
                    emit AdminChanged(_admin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev Upgrade the implementation of the proxy.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
                 */
                function upgradeTo(address newImplementation) external virtual ifAdmin {
                    _upgradeTo(newImplementation);
                }
                /**
                 * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
                 * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
                 * proxied contract.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
                 */
                function upgradeToAndCall(address newImplementation, bytes calldata data) external payable virtual ifAdmin {
                    _upgradeTo(newImplementation);
                    Address.functionDelegateCall(newImplementation, data);
                }
                /**
                 * @dev Returns the current admin.
                 */
                function _admin() internal view virtual returns (address adm) {
                    bytes32 slot = _ADMIN_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        adm := sload(slot)
                    }
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    bytes32 slot = _ADMIN_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        sstore(slot, newAdmin)
                    }
                }
                /**
                 * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
                 */
                function _beforeFallback() internal virtual override {
                    require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                    super._beforeFallback();
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./Proxy.sol";
            import "../utils/Address.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             *
             * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
             * {TransparentUpgradeableProxy}.
             */
            contract UpgradeableProxy is Proxy {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                 * function call, and allows initializating the storage of the proxy like a Solidity constructor.
                 */
                constructor(address _logic, bytes memory _data) public payable {
                    assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
                    _setImplementation(_logic);
                    if(_data.length > 0) {
                        Address.functionDelegateCall(_logic, _data);
                    }
                }
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Returns the current implementation address.
                 */
                function _implementation() internal view virtual override returns (address impl) {
                    bytes32 slot = _IMPLEMENTATION_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        impl := sload(slot)
                    }
                }
                /**
                 * @dev Upgrades the proxy to a new implementation.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal virtual {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract");
                    bytes32 slot = _IMPLEMENTATION_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        sstore(slot, newImplementation)
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.2 <0.8.0;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize, which returns 0 for contracts in
                    // construction, since the code is only stored at the end of the
                    // constructor execution.
                    uint256 size;
                    // solhint-disable-next-line no-inline-assembly
                    assembly { size := extcodesize(account) }
                    return size > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                    (bool success, ) = recipient.call{ value: amount }("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain`call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                  return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.call{ value: value }(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    require(isContract(target), "Address: delegate call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            // solhint-disable-next-line no-inline-assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }
            

            File 2 of 5: GasRefunder
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.8.7;
            import "./IGasRefunder.sol";
            import "@openzeppelin/contracts-0.8/access/Ownable.sol";
            contract GasRefunder is IGasRefunder, Ownable {
                mapping(address => bool) public allowedContracts;
                mapping(address => bool) public allowedRefundees;
                mapping(address => uint256) public lastContractRefund;
                address public disallower;
                struct CommonParameters {
                    uint128 maxRefundeeBalance;
                    uint32 extraGasMargin;
                    uint8 calldataCost;
                    uint64 maxGasTip;
                    uint64 maxGasCost;
                    uint32 maxSingleGasUsage;
                }
                CommonParameters public commonParams;
                enum CommonParameterKey {
                    MAX_REFUNDEE_BALANCE,
                    EXTRA_GAS_MARGIN,
                    CALLDATA_COST,
                    MAX_GAS_TIP,
                    MAX_GAS_COST,
                    MAX_SINGLE_GAS_USAGE
                }
                enum RefundDenyReason {
                    CONTRACT_NOT_ALLOWED,
                    REFUNDEE_NOT_ALLOWED,
                    ALREADY_REFUNDED_THIS_BLOCK,
                    REFUNDEE_ABOVE_MAX_BALANCE,
                    OUT_OF_FUNDS
                }
                event RefundedGasCosts(
                    address indexed refundee,
                    address indexed contractAddress,
                    bool indexed success,
                    uint256 gas,
                    uint256 gasPrice,
                    uint256 amountPaid
                );
                event RefundGasCostsDenied(
                    address indexed refundee,
                    address indexed contractAddress,
                    RefundDenyReason indexed reason,
                    uint256 gas
                );
                event Deposited(address sender, uint256 amount);
                event Withdrawn(address initiator, address destination, uint256 amount);
                event ContractAllowedSet(address indexed addr, bool indexed allowed);
                event RefundeeAllowedSet(address indexed addr, bool indexed allowed);
                event DisallowerSet(address indexed addr);
                event CommonParameterSet(CommonParameterKey indexed parameter, uint256 value);
                constructor() Ownable() {
                    commonParams = CommonParameters({
                        maxRefundeeBalance: 0, // no limit
                        extraGasMargin: 4000, // 4k gas
                        calldataCost: 12, // Between 4 for zero bytes and 16 for non-zero bytes
                        maxGasTip: 2 gwei,
                        maxGasCost: 120 gwei,
                        maxSingleGasUsage: 2e6 // 2 million gas
                    });
                }
                function setDisallower(address addr) external onlyOwner {
                    disallower = addr;
                    emit DisallowerSet(addr);
                }
                function allowContracts(address[] calldata addresses) external onlyOwner {
                    setContractsAllowedImpl(addresses, true);
                }
                function disallowContracts(address[] calldata addresses) external {
                    require(msg.sender == owner() || msg.sender == disallower, "NOT_AUTHORIZED");
                    setContractsAllowedImpl(addresses, false);
                }
                function setContractsAllowedImpl(address[] calldata addresses, bool allow) internal {
                    for (uint256 i = 0; i < addresses.length; i++) {
                        address addr = addresses[i];
                        allowedContracts[addr] = allow;
                        emit ContractAllowedSet(addr, allow);
                    }
                }
                function allowRefundees(address[] calldata addresses) external onlyOwner {
                    setRefundeesAllowedImpl(addresses, true);
                }
                function disallowRefundees(address[] calldata addresses) external {
                    require(msg.sender == owner() || msg.sender == disallower, "NOT_AUTHORIZED");
                    setRefundeesAllowedImpl(addresses, false);
                }
                function setRefundeesAllowedImpl(address[] calldata addresses, bool allow) internal {
                    for (uint256 i = 0; i < addresses.length; i++) {
                        address addr = addresses[i];
                        allowedRefundees[addr] = allow;
                        emit RefundeeAllowedSet(addr, allow);
                    }
                }
                function setMaxRefundeeBalance(uint128 newValue) external onlyOwner {
                    commonParams.maxRefundeeBalance = newValue;
                    emit CommonParameterSet(CommonParameterKey.MAX_REFUNDEE_BALANCE, newValue);
                }
                function setExtraGasMargin(uint32 newValue) external onlyOwner {
                    commonParams.extraGasMargin = newValue;
                    emit CommonParameterSet(CommonParameterKey.EXTRA_GAS_MARGIN, newValue);
                }
                function setCalldataCost(uint8 newValue) external onlyOwner {
                    commonParams.calldataCost = newValue;
                    emit CommonParameterSet(CommonParameterKey.CALLDATA_COST, newValue);
                }
                function setMaxGasTip(uint64 newValue) external onlyOwner {
                    commonParams.maxGasTip = newValue;
                    emit CommonParameterSet(CommonParameterKey.MAX_GAS_TIP, newValue);
                }
                function setMaxGasCost(uint64 newValue) external onlyOwner {
                    commonParams.maxGasCost = newValue;
                    emit CommonParameterSet(CommonParameterKey.MAX_GAS_COST, newValue);
                }
                function setMaxSingleGasUsage(uint32 newValue) external onlyOwner {
                    commonParams.maxSingleGasUsage = newValue;
                    emit CommonParameterSet(CommonParameterKey.MAX_SINGLE_GAS_USAGE, newValue);
                }
                receive() external payable {
                    emit Deposited(msg.sender, msg.value);
                }
                function withdraw(address payable destination, uint256 amount) external onlyOwner {
                    // It's expected that destination is an EOA
                    (bool success, ) = destination.call{ value: amount }("");
                    require(success, "WITHDRAW_FAILED");
                    emit Withdrawn(msg.sender, destination, amount);
                }
                function onGasSpent(
                    address payable refundee,
                    uint256 gasUsed,
                    uint256 calldataSize
                ) external override returns (bool success) {
                    uint256 startGasLeft = gasleft();
                    uint256 ownBalance = address(this).balance;
                    if (ownBalance == 0) {
                        emit RefundGasCostsDenied(refundee, msg.sender, RefundDenyReason.OUT_OF_FUNDS, gasUsed);
                        return false;
                    }
                    if (!allowedContracts[msg.sender]) {
                        emit RefundGasCostsDenied(
                            refundee,
                            msg.sender,
                            RefundDenyReason.CONTRACT_NOT_ALLOWED,
                            gasUsed
                        );
                        return false;
                    }
                    if (!allowedRefundees[refundee]) {
                        emit RefundGasCostsDenied(
                            refundee,
                            msg.sender,
                            RefundDenyReason.REFUNDEE_NOT_ALLOWED,
                            gasUsed
                        );
                        return false;
                    }
                    if (lastContractRefund[msg.sender] == block.number) {
                        // There was already a refund this block, don't refund further
                        emit RefundGasCostsDenied(
                            refundee,
                            msg.sender,
                            RefundDenyReason.ALREADY_REFUNDED_THIS_BLOCK,
                            gasUsed
                        );
                        return false;
                    }
                    lastContractRefund[msg.sender] = block.number;
                    uint256 estGasPrice = block.basefee + commonParams.maxGasTip;
                    if (tx.gasprice < estGasPrice) {
                        estGasPrice = tx.gasprice;
                    }
                    if (commonParams.maxGasCost != 0 && estGasPrice > commonParams.maxGasCost) {
                        estGasPrice = commonParams.maxGasCost;
                    }
                    // Retrieve these variables before measuring gasleft()
                    uint256 refundeeBalance = refundee.balance;
                    uint256 maxRefundeeBalance = commonParams.maxRefundeeBalance;
                    uint256 maxSingleGasUsage = commonParams.maxSingleGasUsage;
                    // Add in a bit of a buffer for the tx costs not measured with gasleft
                    gasUsed +=
                        startGasLeft +
                        commonParams.extraGasMargin +
                        (calldataSize * commonParams.calldataCost);
                    // Split this up into two statements so that gasleft() comes after the storage loads
                    gasUsed -= gasleft();
                    if (maxSingleGasUsage != 0 && gasUsed > maxSingleGasUsage) {
                        gasUsed = maxSingleGasUsage;
                    }
                    uint256 refundAmount = estGasPrice * gasUsed;
                    if (maxRefundeeBalance != 0 && refundeeBalance + refundAmount > maxRefundeeBalance) {
                        if (refundeeBalance > maxRefundeeBalance) {
                            // The refundee is already above their max balance
                            emit RefundGasCostsDenied(
                                refundee,
                                msg.sender,
                                RefundDenyReason.REFUNDEE_ABOVE_MAX_BALANCE,
                                gasUsed
                            );
                            return false;
                        } else {
                            refundAmount = maxRefundeeBalance - refundeeBalance;
                        }
                    }
                    if (refundAmount > ownBalance) {
                        refundAmount = ownBalance;
                    }
                    // It's expected that refundee is an EOA
                    (success, ) = refundee.call{ value: refundAmount }("");
                    emit RefundedGasCosts(refundee, msg.sender, success, gasUsed, estGasPrice, refundAmount);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity >=0.6.11 <0.7.0||>=0.8.7 <0.9.0;
            interface IGasRefunder {
                function onGasSpent(
                    address payable spender,
                    uint256 gasUsed,
                    uint256 calldataSize
                ) external returns (bool success);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            import "../utils/Context.sol";
            /**
             * @dev Contract module which provides a basic access control mechanism, where
             * there is an account (an owner) that can be granted exclusive access to
             * specific functions.
             *
             * By default, the owner account will be the one that deploys the contract. This
             * can later be changed with {transferOwnership}.
             *
             * This module is used through inheritance. It will make available the modifier
             * `onlyOwner`, which can be applied to your functions to restrict their use to
             * the owner.
             */
            abstract contract Ownable is Context {
                address private _owner;
                event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                /**
                 * @dev Initializes the contract setting the deployer as the initial owner.
                 */
                constructor() {
                    _setOwner(_msgSender());
                }
                /**
                 * @dev Returns the address of the current owner.
                 */
                function owner() public view virtual returns (address) {
                    return _owner;
                }
                /**
                 * @dev Throws if called by any account other than the owner.
                 */
                modifier onlyOwner() {
                    require(owner() == _msgSender(), "Ownable: caller is not the owner");
                    _;
                }
                /**
                 * @dev Leaves the contract without owner. It will not be possible to call
                 * `onlyOwner` functions anymore. Can only be called by the current owner.
                 *
                 * NOTE: Renouncing ownership will leave the contract without an owner,
                 * thereby removing any functionality that is only available to the owner.
                 */
                function renounceOwnership() public virtual onlyOwner {
                    _setOwner(address(0));
                }
                /**
                 * @dev Transfers ownership of the contract to a new account (`newOwner`).
                 * Can only be called by the current owner.
                 */
                function transferOwnership(address newOwner) public virtual onlyOwner {
                    require(newOwner != address(0), "Ownable: new owner is the zero address");
                    _setOwner(newOwner);
                }
                function _setOwner(address newOwner) private {
                    address oldOwner = _owner;
                    _owner = newOwner;
                    emit OwnershipTransferred(oldOwner, newOwner);
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            /**
             * @dev Provides information about the current execution context, including the
             * sender of the transaction and its data. While these are generally available
             * via msg.sender and msg.data, they should not be accessed in such a direct
             * manner, since when dealing with meta-transactions the account sending and
             * paying for execution may not be the actual sender (as far as an application
             * is concerned).
             *
             * This contract is only required for intermediate, library-like contracts.
             */
            abstract contract Context {
                function _msgSender() internal view virtual returns (address) {
                    return msg.sender;
                }
                function _msgData() internal view virtual returns (bytes calldata) {
                    return msg.data;
                }
            }
            

            File 3 of 5: SequencerInbox
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./interfaces/ISequencerInbox.sol";
            import "./interfaces/IBridge.sol";
            import "../arch/Marshaling.sol";
            import "../libraries/Cloneable.sol";
            import "../rollup/Rollup.sol";
            import "../validator/IGasRefunder.sol";
            import "./Messages.sol";
            interface OldRollup {
                function sequencerInboxMaxDelayBlocks() external view returns (uint256);
                function sequencerInboxMaxDelaySeconds() external view returns (uint256);
            }
            contract SequencerInbox is ISequencerInbox, Cloneable {
                // Sequencer-Inbox state accumulator
                bytes32[] public override inboxAccs;
                // Number of messages included in the sequencer-inbox; tracked seperately from inboxAccs since multiple messages can be included in a single inboxAcc update (i.e., many messages in a batch, many batches in a single inboxAccs update, etc)
                uint256 public override messageCount;
                // count of messages read from the delayedInbox
                uint256 public totalDelayedMessagesRead;
                IBridge public delayedInbox;
                address private deprecatedSequencer;
                address public rollup;
                mapping(address => bool) public override isSequencer;
                // Window in which only the Sequencer can update the Inbox; this delay is what allows the Sequencer to give receipts with sub-blocktime latency.
                uint256 public override maxDelayBlocks;
                uint256 public override maxDelaySeconds;
                function initialize(
                    IBridge _delayedInbox,
                    address _sequencer,
                    address _rollup
                ) external {
                    require(address(delayedInbox) == address(0), "ALREADY_INIT");
                    delayedInbox = _delayedInbox;
                    isSequencer[_sequencer] = true;
                    rollup = _rollup;
                    // it is assumed that maxDelayBlocks and maxDelaySeconds are set by the rollup
                }
                function postUpgradeInit() external view {
                    // it is assumed the sequencer inbox contract is behind a Proxy controlled by a
                    // proxy admin. this function can only be called by the proxy admin contract
                    address proxyAdmin = ProxyUtil.getProxyAdmin();
                    require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
                }
                /// @notice DEPRECATED - use isSequencer instead
                function sequencer() external view override returns (address) {
                    return deprecatedSequencer;
                }
                function setIsSequencer(address addr, bool newIsSequencer) external override {
                    require(msg.sender == rollup, "ONLY_ROLLUP");
                    isSequencer[addr] = newIsSequencer;
                    emit IsSequencerUpdated(addr, newIsSequencer);
                }
                function setMaxDelay(uint256 newMaxDelayBlocks, uint256 newMaxDelaySeconds) external override {
                    require(msg.sender == rollup, "ONLY_ROLLUP");
                    maxDelayBlocks = newMaxDelayBlocks;
                    maxDelaySeconds = newMaxDelaySeconds;
                    emit MaxDelayUpdated(newMaxDelayBlocks, newMaxDelaySeconds);
                }
                /**
                 * @notice Move messages from the delayed inbox into the Sequencer inbox. Callable by any address. Necessary iff Sequencer hasn't included them before delay period expired.
                 */
                function forceInclusion(
                    uint256 _totalDelayedMessagesRead,
                    uint8 kind,
                    uint256[2] calldata l1BlockAndTimestamp,
                    uint256 inboxSeqNum,
                    uint256 gasPriceL1,
                    address sender,
                    bytes32 messageDataHash,
                    bytes32 delayedAcc
                ) external {
                    require(_totalDelayedMessagesRead > totalDelayedMessagesRead, "DELAYED_BACKWARDS");
                    {
                        bytes32 messageHash = Messages.messageHash(
                            kind,
                            sender,
                            l1BlockAndTimestamp[0],
                            l1BlockAndTimestamp[1],
                            inboxSeqNum,
                            gasPriceL1,
                            messageDataHash
                        );
                        // Can only force-include after the Sequencer-only window has expired.
                        require(l1BlockAndTimestamp[0] + maxDelayBlocks < block.number, "MAX_DELAY_BLOCKS");
                        require(l1BlockAndTimestamp[1] + maxDelaySeconds < block.timestamp, "MAX_DELAY_TIME");
                        // Verify that message hash represents the last message sequence of delayed message to be included
                        bytes32 prevDelayedAcc = 0;
                        if (_totalDelayedMessagesRead > 1) {
                            prevDelayedAcc = delayedInbox.inboxAccs(_totalDelayedMessagesRead - 2);
                        }
                        require(
                            delayedInbox.inboxAccs(_totalDelayedMessagesRead - 1) ==
                                Messages.addMessageToInbox(prevDelayedAcc, messageHash),
                            "DELAYED_ACCUMULATOR"
                        );
                    }
                    uint256 startNum = messageCount;
                    bytes32 beforeAcc = 0;
                    if (inboxAccs.length > 0) {
                        beforeAcc = inboxAccs[inboxAccs.length - 1];
                    }
                    (bytes32 acc, uint256 count) = includeDelayedMessages(
                        beforeAcc,
                        startNum,
                        _totalDelayedMessagesRead,
                        block.number,
                        block.timestamp,
                        delayedAcc
                    );
                    inboxAccs.push(acc);
                    messageCount = count;
                    emit DelayedInboxForced(
                        startNum,
                        beforeAcc,
                        count,
                        _totalDelayedMessagesRead,
                        [acc, delayedAcc],
                        inboxAccs.length - 1
                    );
                }
                function addSequencerL2BatchFromOrigin(
                    bytes calldata transactions,
                    uint256[] calldata lengths,
                    uint256[] calldata sectionsMetadata,
                    bytes32 afterAcc
                ) external {
                    // solhint-disable-next-line avoid-tx-origin
                    require(msg.sender == tx.origin, "origin only");
                    uint256 startNum = messageCount;
                    bytes32 beforeAcc = addSequencerL2BatchImpl(
                        transactions,
                        lengths,
                        sectionsMetadata,
                        afterAcc
                    );
                    emit SequencerBatchDeliveredFromOrigin(
                        startNum,
                        beforeAcc,
                        messageCount,
                        afterAcc,
                        inboxAccs.length - 1
                    );
                }
                function addSequencerL2BatchFromOriginWithGasRefunder(
                    bytes calldata transactions,
                    uint256[] calldata lengths,
                    uint256[] calldata sectionsMetadata,
                    bytes32 afterAcc,
                    IGasRefunder gasRefunder
                ) external {
                    // solhint-disable-next-line avoid-tx-origin
                    require(msg.sender == tx.origin, "origin only");
                    uint256 startGasLeft = gasleft();
                    uint256 calldataSize;
                    assembly {
                        calldataSize := calldatasize()
                    }
                    uint256 startNum = messageCount;
                    bytes32 beforeAcc = addSequencerL2BatchImpl(
                        transactions,
                        lengths,
                        sectionsMetadata,
                        afterAcc
                    );
                    emit SequencerBatchDeliveredFromOrigin(
                        startNum,
                        beforeAcc,
                        messageCount,
                        afterAcc,
                        inboxAccs.length - 1
                    );
                    if (gasRefunder != IGasRefunder(0)) {
                        gasRefunder.onGasSpent(msg.sender, startGasLeft - gasleft(), calldataSize);
                    }
                }
                /**
                 * @notice Sequencer adds a batch to inbox.
                 * @param transactions concatenated bytes of L2 messages
                 * @param lengths length of each txn in transctions (for parsing)
                 * @param sectionsMetadata Each consists of [numItems, l1BlockNumber, l1Timestamp, newTotalDelayedMessagesRead, newDelayedAcc]
                 * @param afterAcc Expected inbox hash after batch is added
                 * @dev sectionsMetadata lets the sequencer delineate new l1Block numbers and l1Timestamps within a given batch; this lets the sequencer minimize the number of batches created (and thus amortizing cost) while still giving timely receipts
                 */
                function addSequencerL2Batch(
                    bytes calldata transactions,
                    uint256[] calldata lengths,
                    uint256[] calldata sectionsMetadata,
                    bytes32 afterAcc
                ) external {
                    uint256 startNum = messageCount;
                    bytes32 beforeAcc = addSequencerL2BatchImpl(
                        transactions,
                        lengths,
                        sectionsMetadata,
                        afterAcc
                    );
                    emit SequencerBatchDelivered(
                        startNum,
                        beforeAcc,
                        messageCount,
                        afterAcc,
                        transactions,
                        lengths,
                        sectionsMetadata,
                        inboxAccs.length - 1,
                        msg.sender
                    );
                }
                function addSequencerL2BatchImpl(
                    bytes memory transactions,
                    uint256[] calldata lengths,
                    uint256[] calldata sectionsMetadata,
                    bytes32 afterAcc
                ) private returns (bytes32 beforeAcc) {
                    require(isSequencer[msg.sender], "ONLY_SEQUENCER");
                    if (inboxAccs.length > 0) {
                        beforeAcc = inboxAccs[inboxAccs.length - 1];
                    }
                    uint256 runningCount = messageCount;
                    bytes32 runningAcc = beforeAcc;
                    uint256 processedItems = 0;
                    uint256 dataOffset;
                    assembly {
                        dataOffset := add(transactions, 32)
                    }
                    for (uint256 i = 0; i + 5 <= sectionsMetadata.length; i += 5) {
                        // Each metadata section consists of:
                        // [numItems, l1BlockNumber, l1Timestamp, newTotalDelayedMessagesRead, newDelayedAcc]
                        {
                            uint256 l1BlockNumber = sectionsMetadata[i + 1];
                            require(l1BlockNumber + maxDelayBlocks >= block.number, "BLOCK_TOO_OLD");
                            require(l1BlockNumber <= block.number, "BLOCK_TOO_NEW");
                        }
                        {
                            uint256 l1Timestamp = sectionsMetadata[i + 2];
                            require(l1Timestamp + maxDelaySeconds >= block.timestamp, "TIME_TOO_OLD");
                            require(l1Timestamp <= block.timestamp, "TIME_TOO_NEW");
                        }
                        {
                            bytes32 prefixHash = keccak256(
                                abi.encodePacked(msg.sender, sectionsMetadata[i + 1], sectionsMetadata[i + 2])
                            );
                            uint256 numItems = sectionsMetadata[i];
                            (runningAcc, runningCount, dataOffset) = calcL2Batch(
                                dataOffset,
                                lengths,
                                processedItems,
                                numItems,
                                prefixHash,
                                runningCount,
                                runningAcc
                            );
                            processedItems += numItems;
                        }
                        uint256 newTotalDelayedMessagesRead = sectionsMetadata[i + 3];
                        require(newTotalDelayedMessagesRead >= totalDelayedMessagesRead, "DELAYED_BACKWARDS");
                        require(newTotalDelayedMessagesRead >= 1, "MUST_DELAYED_INIT");
                        require(
                            totalDelayedMessagesRead >= 1 || sectionsMetadata[i] == 0,
                            "MUST_DELAYED_INIT_START"
                        );
                        // Sequencer decides how many messages (if any) to include from the delayed inbox
                        if (newTotalDelayedMessagesRead > totalDelayedMessagesRead) {
                            (runningAcc, runningCount) = includeDelayedMessages(
                                runningAcc,
                                runningCount,
                                newTotalDelayedMessagesRead,
                                sectionsMetadata[i + 1], // block number
                                sectionsMetadata[i + 2], // timestamp
                                bytes32(sectionsMetadata[i + 4]) // delayed accumulator
                            );
                        }
                    }
                    uint256 startOffset;
                    assembly {
                        startOffset := add(transactions, 32)
                    }
                    require(dataOffset >= startOffset, "OFFSET_OVERFLOW");
                    require(dataOffset <= startOffset + transactions.length, "TRANSACTIONS_OVERRUN");
                    require(runningCount > messageCount, "EMPTY_BATCH");
                    inboxAccs.push(runningAcc);
                    messageCount = runningCount;
                    require(runningAcc == afterAcc, "AFTER_ACC");
                }
                function calcL2Batch(
                    uint256 beforeOffset,
                    uint256[] calldata lengths,
                    uint256 lengthsOffset,
                    uint256 itemCount,
                    bytes32 prefixHash,
                    uint256 beforeCount,
                    bytes32 beforeAcc
                )
                    private
                    pure
                    returns (
                        bytes32 acc,
                        uint256 count,
                        uint256 offset
                    )
                {
                    offset = beforeOffset;
                    count = beforeCount;
                    acc = beforeAcc;
                    itemCount += lengthsOffset;
                    for (uint256 i = lengthsOffset; i < itemCount; i++) {
                        uint256 length = lengths[i];
                        bytes32 messageDataHash;
                        assembly {
                            messageDataHash := keccak256(offset, length)
                        }
                        acc = keccak256(abi.encodePacked(acc, count, prefixHash, messageDataHash));
                        offset += length;
                        count++;
                    }
                    return (acc, count, offset);
                }
                // Precondition: _totalDelayedMessagesRead > totalDelayedMessagesRead
                function includeDelayedMessages(
                    bytes32 acc,
                    uint256 count,
                    uint256 _totalDelayedMessagesRead,
                    uint256 l1BlockNumber,
                    uint256 timestamp,
                    bytes32 delayedAcc
                ) private returns (bytes32, uint256) {
                    require(_totalDelayedMessagesRead <= delayedInbox.messageCount(), "DELAYED_TOO_FAR");
                    require(delayedAcc == delayedInbox.inboxAccs(_totalDelayedMessagesRead - 1), "DELAYED_ACC");
                    acc = keccak256(
                        abi.encodePacked(
                            "Delayed messages:",
                            acc,
                            count,
                            totalDelayedMessagesRead,
                            _totalDelayedMessagesRead,
                            delayedAcc
                        )
                    );
                    count += _totalDelayedMessagesRead - totalDelayedMessagesRead;
                    bytes memory emptyBytes;
                    acc = keccak256(
                        abi.encodePacked(
                            acc,
                            count,
                            keccak256(abi.encodePacked(address(0), l1BlockNumber, timestamp)),
                            keccak256(emptyBytes)
                        )
                    );
                    count++;
                    totalDelayedMessagesRead = _totalDelayedMessagesRead;
                    return (acc, count);
                }
                /**
                 * @notice Prove message count as of provided inbox state hash
                 * @param proof proof data
                 * @param offset offset for parsing proof data
                 * @param inboxAcc target inbox state hash
                 */
                function proveSeqBatchMsgCount(
                    bytes calldata proof,
                    uint256 offset,
                    bytes32 inboxAcc
                ) internal pure returns (uint256, uint256) {
                    uint256 endMessageCount;
                    bytes32 buildingAcc;
                    uint256 seqNum;
                    bytes32 messageHeaderHash;
                    bytes32 messageDataHash;
                    (offset, buildingAcc) = Marshaling.deserializeBytes32(proof, offset);
                    (offset, seqNum) = Marshaling.deserializeInt(proof, offset);
                    (offset, messageHeaderHash) = Marshaling.deserializeBytes32(proof, offset);
                    (offset, messageDataHash) = Marshaling.deserializeBytes32(proof, offset);
                    buildingAcc = keccak256(
                        abi.encodePacked(buildingAcc, seqNum, messageHeaderHash, messageDataHash)
                    );
                    endMessageCount = seqNum + 1;
                    require(buildingAcc == inboxAcc, "BATCH_ACC");
                    return (offset, endMessageCount);
                }
                /**
                 * @notice Show that given messageCount falls inside of some batch and prove/return inboxAcc state. This is used to ensure that the creation of new nodes are replay protected to the state of the inbox, thereby ensuring their validity/invalidy can't be modified upon reorging the inbox contents.
                 * @dev (wrapper in leiu of proveBatchContainsSequenceNumber for sementics)
                 * @return (message count at end of target batch, inbox hash as of target batch)
                 */
                function proveInboxContainsMessage(bytes calldata proof, uint256 _messageCount)
                    external
                    view
                    override
                    returns (uint256, bytes32)
                {
                    return proveInboxContainsMessageImp(proof, _messageCount);
                }
                // deprecated in favor of proveInboxContainsMessage
                function proveBatchContainsSequenceNumber(bytes calldata proof, uint256 _messageCount)
                    external
                    view
                    returns (uint256, bytes32)
                {
                    return proveInboxContainsMessageImp(proof, _messageCount);
                }
                function proveInboxContainsMessageImp(bytes calldata proof, uint256 _messageCount)
                    internal
                    view
                    returns (uint256, bytes32)
                {
                    if (_messageCount == 0) {
                        return (0, 0);
                    }
                    (uint256 offset, uint256 targetInboxStateIndex) = Marshaling.deserializeInt(proof, 0);
                    uint256 messageCountAsOfPreviousInboxState = 0;
                    if (targetInboxStateIndex > 0) {
                        (offset, messageCountAsOfPreviousInboxState) = proveSeqBatchMsgCount(
                            proof,
                            offset,
                            inboxAccs[targetInboxStateIndex - 1]
                        );
                    }
                    bytes32 targetInboxState = inboxAccs[targetInboxStateIndex];
                    uint256 messageCountAsOfTargetInboxState;
                    (offset, messageCountAsOfTargetInboxState) = proveSeqBatchMsgCount(
                        proof,
                        offset,
                        targetInboxState
                    );
                    require(_messageCount > messageCountAsOfPreviousInboxState, "BATCH_START");
                    require(_messageCount <= messageCountAsOfTargetInboxState, "BATCH_END");
                    return (messageCountAsOfTargetInboxState, targetInboxState);
                }
                function getInboxAccsLength() external view override returns (uint256) {
                    return inboxAccs.length;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface ISequencerInbox {
                event SequencerBatchDelivered(
                    uint256 indexed firstMessageNum,
                    bytes32 indexed beforeAcc,
                    uint256 newMessageCount,
                    bytes32 afterAcc,
                    bytes transactions,
                    uint256[] lengths,
                    uint256[] sectionsMetadata,
                    uint256 seqBatchIndex,
                    address sequencer
                );
                event SequencerBatchDeliveredFromOrigin(
                    uint256 indexed firstMessageNum,
                    bytes32 indexed beforeAcc,
                    uint256 newMessageCount,
                    bytes32 afterAcc,
                    uint256 seqBatchIndex
                );
                event DelayedInboxForced(
                    uint256 indexed firstMessageNum,
                    bytes32 indexed beforeAcc,
                    uint256 newMessageCount,
                    uint256 totalDelayedMessagesRead,
                    bytes32[2] afterAccAndDelayed,
                    uint256 seqBatchIndex
                );
                /// @notice DEPRECATED - look at IsSequencerUpdated for new updates
                // event SequencerAddressUpdated(address newAddress);
                event IsSequencerUpdated(address addr, bool isSequencer);
                event MaxDelayUpdated(uint256 newMaxDelayBlocks, uint256 newMaxDelaySeconds);
                /// @notice DEPRECATED - look at MaxDelayUpdated for new updates
                // event MaxDelayBlocksUpdated(uint256 newValue);
                /// @notice DEPRECATED - look at MaxDelayUpdated for new updates
                // event MaxDelaySecondsUpdated(uint256 newValue);
                function setMaxDelay(uint256 newMaxDelayBlocks, uint256 newMaxDelaySeconds) external;
                function setIsSequencer(address addr, bool isSequencer) external;
                function messageCount() external view returns (uint256);
                function maxDelayBlocks() external view returns (uint256);
                function maxDelaySeconds() external view returns (uint256);
                function inboxAccs(uint256 index) external view returns (bytes32);
                function getInboxAccsLength() external view returns (uint256);
                function proveInboxContainsMessage(bytes calldata proof, uint256 inboxCount)
                    external
                    view
                    returns (uint256, bytes32);
                /// @notice DEPRECATED - use isSequencer instead
                function sequencer() external view returns (address);
                function isSequencer(address seq) external view returns (bool);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface IBridge {
                event MessageDelivered(
                    uint256 indexed messageIndex,
                    bytes32 indexed beforeInboxAcc,
                    address inbox,
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                );
                event BridgeCallTriggered(
                    address indexed outbox,
                    address indexed destAddr,
                    uint256 amount,
                    bytes data
                );
                event InboxToggle(address indexed inbox, bool enabled);
                event OutboxToggle(address indexed outbox, bool enabled);
                function deliverMessageToInbox(
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                ) external payable returns (uint256);
                function executeCall(
                    address destAddr,
                    uint256 amount,
                    bytes calldata data
                ) external returns (bool success, bytes memory returnData);
                // These are only callable by the admin
                function setInbox(address inbox, bool enabled) external;
                function setOutbox(address inbox, bool enabled) external;
                // View functions
                function activeOutbox() external view returns (address);
                function allowedInboxes(address inbox) external view returns (bool);
                function allowedOutboxes(address outbox) external view returns (bool);
                function inboxAccs(uint256 index) external view returns (bytes32);
                function messageCount() external view returns (uint256);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./Value.sol";
            import "./Hashing.sol";
            import "../libraries/BytesLib.sol";
            library Marshaling {
                using BytesLib for bytes;
                using Value for Value.Data;
                function deserializeHashPreImage(bytes memory data, uint256 startOffset)
                    internal
                    pure
                    returns (uint256 offset, Value.Data memory value)
                {
                    require(data.length >= startOffset && data.length - startOffset >= 64, "too short");
                    bytes32 hashData;
                    uint256 size;
                    (offset, hashData) = extractBytes32(data, startOffset);
                    (offset, size) = deserializeInt(data, offset);
                    return (offset, Value.newTuplePreImage(hashData, size));
                }
                function deserializeInt(bytes memory data, uint256 startOffset)
                    internal
                    pure
                    returns (
                        uint256, // offset
                        uint256 // val
                    )
                {
                    require(data.length >= startOffset && data.length - startOffset >= 32, "too short");
                    return (startOffset + 32, data.toUint(startOffset));
                }
                function deserializeBytes32(bytes memory data, uint256 startOffset)
                    internal
                    pure
                    returns (
                        uint256, // offset
                        bytes32 // val
                    )
                {
                    require(data.length >= startOffset && data.length - startOffset >= 32, "too short");
                    return (startOffset + 32, data.toBytes32(startOffset));
                }
                function deserializeCodePoint(bytes memory data, uint256 startOffset)
                    internal
                    pure
                    returns (
                        uint256, // offset
                        Value.Data memory // val
                    )
                {
                    uint256 offset = startOffset;
                    uint8 immediateType;
                    uint8 opCode;
                    Value.Data memory immediate;
                    bytes32 nextHash;
                    (offset, immediateType) = extractUint8(data, offset);
                    (offset, opCode) = extractUint8(data, offset);
                    if (immediateType == 1) {
                        (offset, immediate) = deserialize(data, offset);
                    }
                    (offset, nextHash) = extractBytes32(data, offset);
                    if (immediateType == 1) {
                        return (offset, Value.newCodePoint(opCode, nextHash, immediate));
                    }
                    return (offset, Value.newCodePoint(opCode, nextHash));
                }
                function deserializeTuple(
                    uint8 memberCount,
                    bytes memory data,
                    uint256 startOffset
                )
                    internal
                    pure
                    returns (
                        uint256, // offset
                        Value.Data[] memory // val
                    )
                {
                    uint256 offset = startOffset;
                    Value.Data[] memory members = new Value.Data[](memberCount);
                    for (uint8 i = 0; i < memberCount; i++) {
                        (offset, members[i]) = deserialize(data, offset);
                    }
                    return (offset, members);
                }
                function deserialize(bytes memory data, uint256 startOffset)
                    internal
                    pure
                    returns (
                        uint256, // offset
                        Value.Data memory // val
                    )
                {
                    require(startOffset < data.length, "invalid offset");
                    (uint256 offset, uint8 valType) = extractUint8(data, startOffset);
                    if (valType == Value.intTypeCode()) {
                        uint256 intVal;
                        (offset, intVal) = deserializeInt(data, offset);
                        return (offset, Value.newInt(intVal));
                    } else if (valType == Value.codePointTypeCode()) {
                        return deserializeCodePoint(data, offset);
                    } else if (valType == Value.bufferTypeCode()) {
                        bytes32 hashVal;
                        (offset, hashVal) = deserializeBytes32(data, offset);
                        return (offset, Value.newBuffer(hashVal));
                    } else if (valType == Value.tuplePreImageTypeCode()) {
                        return deserializeHashPreImage(data, offset);
                    } else if (valType >= Value.tupleTypeCode() && valType < Value.valueTypeCode()) {
                        uint8 tupLength = uint8(valType - Value.tupleTypeCode());
                        Value.Data[] memory tupleVal;
                        (offset, tupleVal) = deserializeTuple(tupLength, data, offset);
                        return (offset, Value.newTuple(tupleVal));
                    }
                    require(false, "invalid typecode");
                }
                function extractUint8(bytes memory data, uint256 startOffset)
                    private
                    pure
                    returns (
                        uint256, // offset
                        uint8 // val
                    )
                {
                    return (startOffset + 1, uint8(data[startOffset]));
                }
                function extractBytes32(bytes memory data, uint256 startOffset)
                    private
                    pure
                    returns (
                        uint256, // offset
                        bytes32 // val
                    )
                {
                    return (startOffset + 32, data.toBytes32(startOffset));
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2020, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./ICloneable.sol";
            contract Cloneable is ICloneable {
                string private constant NOT_CLONE = "NOT_CLONE";
                bool private isMasterCopy;
                constructor() public {
                    isMasterCopy = true;
                }
                function isMaster() external view override returns (bool) {
                    return isMasterCopy;
                }
                function safeSelfDestruct(address payable dest) internal {
                    require(!isMasterCopy, NOT_CLONE);
                    selfdestruct(dest);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "@openzeppelin/contracts/utils/Pausable.sol";
            import "@openzeppelin/contracts/proxy/Proxy.sol";
            import "@openzeppelin/contracts/utils/Address.sol";
            import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
            import "./RollupEventBridge.sol";
            import "./RollupCore.sol";
            import "./RollupLib.sol";
            import "./INode.sol";
            import "./INodeFactory.sol";
            import "../challenge/IChallenge.sol";
            import "../challenge/IChallengeFactory.sol";
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/IOutbox.sol";
            import "../bridge/Messages.sol";
            import "../libraries/ProxyUtil.sol";
            import "../libraries/Cloneable.sol";
            import "./facets/IRollupFacets.sol";
            abstract contract RollupBase is Cloneable, RollupCore, Pausable {
                // Rollup Config
                uint256 public confirmPeriodBlocks;
                uint256 public extraChallengeTimeBlocks;
                uint256 public avmGasSpeedLimitPerBlock;
                uint256 public baseStake;
                // Bridge is an IInbox and IOutbox
                IBridge public delayedBridge;
                ISequencerInbox public sequencerBridge;
                IOutbox public outbox;
                RollupEventBridge public rollupEventBridge;
                IChallengeFactory public challengeFactory;
                INodeFactory public nodeFactory;
                address public owner;
                address public stakeToken;
                uint256 public minimumAssertionPeriod;
                uint256 public STORAGE_GAP_1;
                uint256 public STORAGE_GAP_2;
                uint256 public challengeExecutionBisectionDegree;
                address[] internal facets;
                mapping(address => bool) isValidator;
                /// @notice DEPRECATED -- this method is deprecated but still mantained for backward compatibility
                /// @dev this actually returns the avmGasSpeedLimitPerBlock
                /// @return this actually returns the avmGasSpeedLimitPerBlock
                function arbGasSpeedLimitPerBlock() external view returns (uint256) {
                    return avmGasSpeedLimitPerBlock;
                }
            }
            contract Rollup is Proxy, RollupBase {
                using Address for address;
                constructor(uint256 _confirmPeriodBlocks) public Cloneable() Pausable() {
                    // constructor is used so logic contract can't be init'ed
                    confirmPeriodBlocks = _confirmPeriodBlocks;
                    require(isInit(), "CONSTRUCTOR_NOT_INIT");
                }
                function isInit() internal view returns (bool) {
                    return confirmPeriodBlocks != 0;
                }
                // _rollupParams = [ confirmPeriodBlocks, extraChallengeTimeBlocks, avmGasSpeedLimitPerBlock, baseStake ]
                // connectedContracts = [delayedBridge, sequencerInbox, outbox, rollupEventBridge, challengeFactory, nodeFactory]
                function initialize(
                    bytes32 _machineHash,
                    uint256[4] calldata _rollupParams,
                    address _stakeToken,
                    address _owner,
                    bytes calldata _extraConfig,
                    address[6] calldata connectedContracts,
                    address[2] calldata _facets,
                    uint256[2] calldata sequencerInboxParams
                ) public {
                    require(!isInit(), "ALREADY_INIT");
                    // calls initialize method in user facet
                    require(_facets[0].isContract(), "FACET_0_NOT_CONTRACT");
                    require(_facets[1].isContract(), "FACET_1_NOT_CONTRACT");
                    (bool success, ) = _facets[1].delegatecall(
                        abi.encodeWithSelector(IRollupUser.initialize.selector, _stakeToken)
                    );
                    require(success, "FAIL_INIT_FACET");
                    delayedBridge = IBridge(connectedContracts[0]);
                    sequencerBridge = ISequencerInbox(connectedContracts[1]);
                    outbox = IOutbox(connectedContracts[2]);
                    delayedBridge.setOutbox(connectedContracts[2], true);
                    rollupEventBridge = RollupEventBridge(connectedContracts[3]);
                    delayedBridge.setInbox(connectedContracts[3], true);
                    rollupEventBridge.rollupInitialized(
                        _rollupParams[0],
                        _rollupParams[2],
                        _owner,
                        _extraConfig
                    );
                    challengeFactory = IChallengeFactory(connectedContracts[4]);
                    nodeFactory = INodeFactory(connectedContracts[5]);
                    INode node = createInitialNode(_machineHash);
                    initializeCore(node);
                    confirmPeriodBlocks = _rollupParams[0];
                    extraChallengeTimeBlocks = _rollupParams[1];
                    avmGasSpeedLimitPerBlock = _rollupParams[2];
                    baseStake = _rollupParams[3];
                    owner = _owner;
                    // A little over 15 minutes
                    minimumAssertionPeriod = 75;
                    challengeExecutionBisectionDegree = 400;
                    sequencerBridge.setMaxDelay(sequencerInboxParams[0], sequencerInboxParams[1]);
                    // facets[0] == admin, facets[1] == user
                    facets = _facets;
                    emit RollupCreated(_machineHash);
                    require(isInit(), "INITIALIZE_NOT_INIT");
                }
                function postUpgradeInit() external {
                    // it is assumed the rollup contract is behind a Proxy controlled by a proxy admin
                    // this function can only be called by the proxy admin contract
                    address proxyAdmin = ProxyUtil.getProxyAdmin();
                    require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
                    // this upgrade moves the delay blocks and seconds tracking to the sequencer inbox
                    // because of that we need to update the admin facet logic to allow the owner to set
                    // these values in the sequencer inbox
                    STORAGE_GAP_1 = 0;
                    STORAGE_GAP_2 = 0;
                }
                function createInitialNode(bytes32 _machineHash) private returns (INode) {
                    bytes32 state = RollupLib.stateHash(
                        RollupLib.ExecutionState(
                            0, // total gas used
                            _machineHash,
                            0, // inbox count
                            0, // send count
                            0, // log count
                            0, // send acc
                            0, // log acc
                            block.number, // block proposed
                            1 // Initialization message already in inbox
                        )
                    );
                    return
                        INode(
                            nodeFactory.createNode(
                                state,
                                0, // challenge hash (not challengeable)
                                0, // confirm data
                                0, // prev node
                                block.number // deadline block (not challengeable)
                            )
                        );
                }
                /**
                 * This contract uses a dispatch pattern from EIP-2535: Diamonds
                 * together with Open Zeppelin's proxy
                 */
                function getFacets() external view returns (address, address) {
                    return (getAdminFacet(), getUserFacet());
                }
                function getAdminFacet() public view returns (address) {
                    return facets[0];
                }
                function getUserFacet() public view returns (address) {
                    return facets[1];
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual override returns (address) {
                    require(msg.data.length >= 4, "NO_FUNC_SIG");
                    address rollupOwner = owner;
                    // if there is an owner and it is the sender, delegate to admin facet
                    address target = rollupOwner != address(0) && rollupOwner == msg.sender
                        ? getAdminFacet()
                        : getUserFacet();
                    require(target.isContract(), "TARGET_NOT_CONTRACT");
                    return target;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity >=0.6.11 <0.7.0||>=0.8.7 <0.9.0;
            interface IGasRefunder {
                function onGasSpent(
                    address payable spender,
                    uint256 gasUsed,
                    uint256 calldataSize
                ) external returns (bool success);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library Messages {
                function messageHash(
                    uint8 kind,
                    address sender,
                    uint256 blockNumber,
                    uint256 timestamp,
                    uint256 inboxSeqNum,
                    uint256 gasPriceL1,
                    bytes32 messageDataHash
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                kind,
                                sender,
                                blockNumber,
                                timestamp,
                                inboxSeqNum,
                                gasPriceL1,
                                messageDataHash
                            )
                        );
                }
                function addMessageToInbox(bytes32 inbox, bytes32 message) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(inbox, message));
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library Value {
                uint8 internal constant INT_TYPECODE = 0;
                uint8 internal constant CODE_POINT_TYPECODE = 1;
                uint8 internal constant HASH_PRE_IMAGE_TYPECODE = 2;
                uint8 internal constant TUPLE_TYPECODE = 3;
                uint8 internal constant BUFFER_TYPECODE = TUPLE_TYPECODE + 9;
                // All values received from clients will have type codes less than the VALUE_TYPE_COUNT
                uint8 internal constant VALUE_TYPE_COUNT = TUPLE_TYPECODE + 10;
                // The following types do not show up in the marshalled format and is
                // only used for internal tracking purposes
                uint8 internal constant HASH_ONLY = 100;
                struct CodePoint {
                    uint8 opcode;
                    bytes32 nextCodePoint;
                    Data[] immediate;
                }
                struct Data {
                    uint256 intVal;
                    CodePoint cpVal;
                    Data[] tupleVal;
                    bytes32 bufferHash;
                    uint8 typeCode;
                    uint256 size;
                }
                function tupleTypeCode() internal pure returns (uint8) {
                    return TUPLE_TYPECODE;
                }
                function tuplePreImageTypeCode() internal pure returns (uint8) {
                    return HASH_PRE_IMAGE_TYPECODE;
                }
                function intTypeCode() internal pure returns (uint8) {
                    return INT_TYPECODE;
                }
                function bufferTypeCode() internal pure returns (uint8) {
                    return BUFFER_TYPECODE;
                }
                function codePointTypeCode() internal pure returns (uint8) {
                    return CODE_POINT_TYPECODE;
                }
                function valueTypeCode() internal pure returns (uint8) {
                    return VALUE_TYPE_COUNT;
                }
                function hashOnlyTypeCode() internal pure returns (uint8) {
                    return HASH_ONLY;
                }
                function isValidTupleSize(uint256 size) internal pure returns (bool) {
                    return size <= 8;
                }
                function typeCodeVal(Data memory val) internal pure returns (Data memory) {
                    if (val.typeCode == 2) {
                        // Map HashPreImage to Tuple
                        return newInt(TUPLE_TYPECODE);
                    }
                    return newInt(val.typeCode);
                }
                function valLength(Data memory val) internal pure returns (uint8) {
                    if (val.typeCode == TUPLE_TYPECODE) {
                        return uint8(val.tupleVal.length);
                    } else {
                        return 1;
                    }
                }
                function isInt(Data memory val) internal pure returns (bool) {
                    return val.typeCode == INT_TYPECODE;
                }
                function isInt64(Data memory val) internal pure returns (bool) {
                    return val.typeCode == INT_TYPECODE && val.intVal < (1 << 64);
                }
                function isCodePoint(Data memory val) internal pure returns (bool) {
                    return val.typeCode == CODE_POINT_TYPECODE;
                }
                function isTuple(Data memory val) internal pure returns (bool) {
                    return val.typeCode == TUPLE_TYPECODE;
                }
                function isBuffer(Data memory val) internal pure returns (bool) {
                    return val.typeCode == BUFFER_TYPECODE;
                }
                function newEmptyTuple() internal pure returns (Data memory) {
                    return newTuple(new Data[](0));
                }
                function newBoolean(bool val) internal pure returns (Data memory) {
                    if (val) {
                        return newInt(1);
                    } else {
                        return newInt(0);
                    }
                }
                function newInt(uint256 _val) internal pure returns (Data memory) {
                    return
                        Data(_val, CodePoint(0, 0, new Data[](0)), new Data[](0), 0, INT_TYPECODE, uint256(1));
                }
                function newHashedValue(bytes32 valueHash, uint256 valueSize)
                    internal
                    pure
                    returns (Data memory)
                {
                    return
                        Data(
                            uint256(valueHash),
                            CodePoint(0, 0, new Data[](0)),
                            new Data[](0),
                            0,
                            HASH_ONLY,
                            valueSize
                        );
                }
                function newTuple(Data[] memory _val) internal pure returns (Data memory) {
                    require(isValidTupleSize(_val.length), "Tuple must have valid size");
                    uint256 size = 1;
                    for (uint256 i = 0; i < _val.length; i++) {
                        size += _val[i].size;
                    }
                    return Data(0, CodePoint(0, 0, new Data[](0)), _val, 0, TUPLE_TYPECODE, size);
                }
                function newTuplePreImage(bytes32 preImageHash, uint256 size)
                    internal
                    pure
                    returns (Data memory)
                {
                    return
                        Data(
                            uint256(preImageHash),
                            CodePoint(0, 0, new Data[](0)),
                            new Data[](0),
                            0,
                            HASH_PRE_IMAGE_TYPECODE,
                            size
                        );
                }
                function newCodePoint(uint8 opCode, bytes32 nextHash) internal pure returns (Data memory) {
                    return newCodePoint(CodePoint(opCode, nextHash, new Data[](0)));
                }
                function newCodePoint(
                    uint8 opCode,
                    bytes32 nextHash,
                    Data memory immediate
                ) internal pure returns (Data memory) {
                    Data[] memory imm = new Data[](1);
                    imm[0] = immediate;
                    return newCodePoint(CodePoint(opCode, nextHash, imm));
                }
                function newCodePoint(CodePoint memory _val) private pure returns (Data memory) {
                    return Data(0, _val, new Data[](0), 0, CODE_POINT_TYPECODE, uint256(1));
                }
                function newBuffer(bytes32 bufHash) internal pure returns (Data memory) {
                    return
                        Data(
                            uint256(0),
                            CodePoint(0, 0, new Data[](0)),
                            new Data[](0),
                            bufHash,
                            BUFFER_TYPECODE,
                            uint256(1)
                        );
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2020, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./Value.sol";
            library Hashing {
                using Hashing for Value.Data;
                using Value for Value.CodePoint;
                function keccak1(bytes32 b) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(b));
                }
                function keccak2(bytes32 a, bytes32 b) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(a, b));
                }
                function bytes32FromArray(
                    bytes memory arr,
                    uint256 offset,
                    uint256 arrLength
                ) internal pure returns (uint256) {
                    uint256 res = 0;
                    for (uint256 i = 0; i < 32; i++) {
                        res = res << 8;
                        bytes1 b = arrLength > offset + i ? arr[offset + i] : bytes1(0);
                        res = res | uint256(uint8(b));
                    }
                    return res;
                }
                /*
                 * !! Note that dataLength must be a power of two !!
                 *
                 * If you have an arbitrary data length, you can round it up with roundUpToPow2.
                 * The boolean return value tells if the data segment data[startOffset..startOffset+dataLength] only included zeroes.
                 * If pack is true, the returned value is the merkle hash where trailing zeroes are ignored, that is,
                 *   if h is the smallest height for which all data[startOffset+2**h..] are zero, merkle hash of data[startOffset..startOffset+2**h] is returned.
                 * If all elements in the data segment are zero (and pack is true), keccak1(bytes32(0)) is returned.
                 */
                function merkleRoot(
                    bytes memory data,
                    uint256 rawDataLength,
                    uint256 startOffset,
                    uint256 dataLength,
                    bool pack
                ) internal pure returns (bytes32, bool) {
                    if (dataLength <= 32) {
                        if (startOffset >= rawDataLength) {
                            return (keccak1(bytes32(0)), true);
                        }
                        bytes32 res = keccak1(bytes32(bytes32FromArray(data, startOffset, rawDataLength)));
                        return (res, res == keccak1(bytes32(0)));
                    }
                    (bytes32 h2, bool zero2) =
                        merkleRoot(data, rawDataLength, startOffset + dataLength / 2, dataLength / 2, false);
                    if (zero2 && pack) {
                        return merkleRoot(data, rawDataLength, startOffset, dataLength / 2, pack);
                    }
                    (bytes32 h1, bool zero1) =
                        merkleRoot(data, rawDataLength, startOffset, dataLength / 2, false);
                    return (keccak2(h1, h2), zero1 && zero2);
                }
                function roundUpToPow2(uint256 len) internal pure returns (uint256) {
                    if (len <= 1) return 1;
                    else return 2 * roundUpToPow2((len + 1) / 2);
                }
                function bytesToBufferHash(
                    bytes memory buf,
                    uint256 startOffset,
                    uint256 length
                ) internal pure returns (bytes32) {
                    (bytes32 mhash, ) =
                        merkleRoot(buf, startOffset + length, startOffset, roundUpToPow2(length), true);
                    return keccak2(bytes32(uint256(123)), mhash);
                }
                function hashInt(uint256 val) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(val));
                }
                function hashCodePoint(Value.CodePoint memory cp) internal pure returns (bytes32) {
                    assert(cp.immediate.length < 2);
                    if (cp.immediate.length == 0) {
                        return
                            keccak256(abi.encodePacked(Value.codePointTypeCode(), cp.opcode, cp.nextCodePoint));
                    }
                    return
                        keccak256(
                            abi.encodePacked(
                                Value.codePointTypeCode(),
                                cp.opcode,
                                cp.immediate[0].hash(),
                                cp.nextCodePoint
                            )
                        );
                }
                function hashTuplePreImage(bytes32 innerHash, uint256 valueSize)
                    internal
                    pure
                    returns (bytes32)
                {
                    return keccak256(abi.encodePacked(uint8(Value.tupleTypeCode()), innerHash, valueSize));
                }
                function hash(Value.Data memory val) internal pure returns (bytes32) {
                    if (val.typeCode == Value.intTypeCode()) {
                        return hashInt(val.intVal);
                    } else if (val.typeCode == Value.codePointTypeCode()) {
                        return hashCodePoint(val.cpVal);
                    } else if (val.typeCode == Value.tuplePreImageTypeCode()) {
                        return hashTuplePreImage(bytes32(val.intVal), val.size);
                    } else if (val.typeCode == Value.tupleTypeCode()) {
                        Value.Data memory preImage = getTuplePreImage(val.tupleVal);
                        return preImage.hash();
                    } else if (val.typeCode == Value.hashOnlyTypeCode()) {
                        return bytes32(val.intVal);
                    } else if (val.typeCode == Value.bufferTypeCode()) {
                        return keccak256(abi.encodePacked(uint256(123), val.bufferHash));
                    } else {
                        require(false, "Invalid type code");
                    }
                }
                function getTuplePreImage(Value.Data[] memory vals) internal pure returns (Value.Data memory) {
                    require(vals.length <= 8, "Invalid tuple length");
                    bytes32[] memory hashes = new bytes32[](vals.length);
                    uint256 hashCount = hashes.length;
                    uint256 size = 1;
                    for (uint256 i = 0; i < hashCount; i++) {
                        hashes[i] = vals[i].hash();
                        size += vals[i].size;
                    }
                    bytes32 firstHash = keccak256(abi.encodePacked(uint8(hashes.length), hashes));
                    return Value.newTuplePreImage(firstHash, size);
                }
            }
            // SPDX-License-Identifier: MIT
            /*
             * @title Solidity Bytes Arrays Utils
             * @author Gonçalo Sá <goncalo.sa@consensys.net>
             *
             * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
             *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
             */
            pragma solidity ^0.6.11;
            /* solhint-disable no-inline-assembly */
            library BytesLib {
                function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
                    require(_bytes.length >= (_start + 20), "Read out of bounds");
                    address tempAddress;
                    assembly {
                        tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
                    }
                    return tempAddress;
                }
                function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
                    require(_bytes.length >= (_start + 1), "Read out of bounds");
                    uint8 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x1), _start))
                    }
                    return tempUint;
                }
                function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
                    require(_bytes.length >= (_start + 32), "Read out of bounds");
                    uint256 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x20), _start))
                    }
                    return tempUint;
                }
                function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
                    require(_bytes.length >= (_start + 32), "Read out of bounds");
                    bytes32 tempBytes32;
                    assembly {
                        tempBytes32 := mload(add(add(_bytes, 0x20), _start))
                    }
                    return tempBytes32;
                }
            }
            /* solhint-enable no-inline-assembly */
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface ICloneable {
                function isMaster() external view returns (bool);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./Context.sol";
            /**
             * @dev Contract module which allows children to implement an emergency stop
             * mechanism that can be triggered by an authorized account.
             *
             * This module is used through inheritance. It will make available the
             * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
             * the functions of your contract. Note that they will not be pausable by
             * simply including this module, only once the modifiers are put in place.
             */
            abstract contract Pausable is Context {
                /**
                 * @dev Emitted when the pause is triggered by `account`.
                 */
                event Paused(address account);
                /**
                 * @dev Emitted when the pause is lifted by `account`.
                 */
                event Unpaused(address account);
                bool private _paused;
                /**
                 * @dev Initializes the contract in unpaused state.
                 */
                constructor () internal {
                    _paused = false;
                }
                /**
                 * @dev Returns true if the contract is paused, and false otherwise.
                 */
                function paused() public view virtual returns (bool) {
                    return _paused;
                }
                /**
                 * @dev Modifier to make a function callable only when the contract is not paused.
                 *
                 * Requirements:
                 *
                 * - The contract must not be paused.
                 */
                modifier whenNotPaused() {
                    require(!paused(), "Pausable: paused");
                    _;
                }
                /**
                 * @dev Modifier to make a function callable only when the contract is paused.
                 *
                 * Requirements:
                 *
                 * - The contract must be paused.
                 */
                modifier whenPaused() {
                    require(paused(), "Pausable: not paused");
                    _;
                }
                /**
                 * @dev Triggers stopped state.
                 *
                 * Requirements:
                 *
                 * - The contract must not be paused.
                 */
                function _pause() internal virtual whenNotPaused {
                    _paused = true;
                    emit Paused(_msgSender());
                }
                /**
                 * @dev Returns to normal state.
                 *
                 * Requirements:
                 *
                 * - The contract must be paused.
                 */
                function _unpause() internal virtual whenPaused {
                    _paused = false;
                    emit Unpaused(_msgSender());
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 { revert(0, returndatasize()) }
                        default { return(0, returndatasize()) }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overriden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.2 <0.8.0;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize, which returns 0 for contracts in
                    // construction, since the code is only stored at the end of the
                    // constructor execution.
                    uint256 size;
                    // solhint-disable-next-line no-inline-assembly
                    assembly { size := extcodesize(account) }
                    return size > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                    (bool success, ) = recipient.call{ value: amount }("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain`call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                  return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.call{ value: value }(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    require(isContract(target), "Address: delegate call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            // solhint-disable-next-line no-inline-assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev Interface of the ERC20 standard as defined in the EIP.
             */
            interface IERC20 {
                /**
                 * @dev Returns the amount of tokens in existence.
                 */
                function totalSupply() external view returns (uint256);
                /**
                 * @dev Returns the amount of tokens owned by `account`.
                 */
                function balanceOf(address account) external view returns (uint256);
                /**
                 * @dev Moves `amount` tokens from the caller's account to `recipient`.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transfer(address recipient, uint256 amount) external returns (bool);
                /**
                 * @dev Returns the remaining number of tokens that `spender` will be
                 * allowed to spend on behalf of `owner` through {transferFrom}. This is
                 * zero by default.
                 *
                 * This value changes when {approve} or {transferFrom} are called.
                 */
                function allowance(address owner, address spender) external view returns (uint256);
                /**
                 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * IMPORTANT: Beware that changing an allowance with this method brings the risk
                 * that someone may use both the old and the new allowance by unfortunate
                 * transaction ordering. One possible solution to mitigate this race
                 * condition is to first reduce the spender's allowance to 0 and set the
                 * desired value afterwards:
                 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                 *
                 * Emits an {Approval} event.
                 */
                function approve(address spender, uint256 amount) external returns (bool);
                /**
                 * @dev Moves `amount` tokens from `sender` to `recipient` using the
                 * allowance mechanism. `amount` is then deducted from the caller's
                 * allowance.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
                /**
                 * @dev Emitted when `value` tokens are moved from one account (`from`) to
                 * another (`to`).
                 *
                 * Note that `value` may be zero.
                 */
                event Transfer(address indexed from, address indexed to, uint256 value);
                /**
                 * @dev Emitted when the allowance of a `spender` for an `owner` is set by
                 * a call to {approve}. `value` is the new allowance.
                 */
                event Approval(address indexed owner, address indexed spender, uint256 value);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./Rollup.sol";
            import "./facets/IRollupFacets.sol";
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/IMessageProvider.sol";
            import "./INode.sol";
            import "../libraries/Cloneable.sol";
            contract RollupEventBridge is IMessageProvider, Cloneable {
                uint8 internal constant INITIALIZATION_MSG_TYPE = 11;
                uint8 internal constant ROLLUP_PROTOCOL_EVENT_TYPE = 8;
                uint8 internal constant CREATE_NODE_EVENT = 0;
                uint8 internal constant CONFIRM_NODE_EVENT = 1;
                uint8 internal constant REJECT_NODE_EVENT = 2;
                uint8 internal constant STAKE_CREATED_EVENT = 3;
                IBridge bridge;
                address rollup;
                modifier onlyRollup() {
                    require(msg.sender == rollup, "ONLY_ROLLUP");
                    _;
                }
                function initialize(address _bridge, address _rollup) external {
                    require(rollup == address(0), "ALREADY_INIT");
                    bridge = IBridge(_bridge);
                    rollup = _rollup;
                }
                function rollupInitialized(
                    uint256 confirmPeriodBlocks,
                    uint256 avmGasSpeedLimitPerBlock,
                    address owner,
                    bytes calldata extraConfig
                ) external onlyRollup {
                    bytes memory initMsg = abi.encodePacked(
                        keccak256("ChallengePeriodEthBlocks"),
                        confirmPeriodBlocks,
                        keccak256("SpeedLimitPerSecond"),
                        avmGasSpeedLimitPerBlock / 100, // convert avm gas to arbgas
                        keccak256("ChainOwner"),
                        uint256(uint160(bytes20(owner))),
                        extraConfig
                    );
                    uint256 num = bridge.deliverMessageToInbox(
                        INITIALIZATION_MSG_TYPE,
                        address(0),
                        keccak256(initMsg)
                    );
                    emit InboxMessageDelivered(num, initMsg);
                }
                function nodeCreated(
                    uint256 nodeNum,
                    uint256 prev,
                    uint256 deadline,
                    address asserter
                ) external onlyRollup {
                    deliverToBridge(
                        abi.encodePacked(
                            CREATE_NODE_EVENT,
                            nodeNum,
                            prev,
                            block.number,
                            deadline,
                            uint256(uint160(bytes20(asserter)))
                        )
                    );
                }
                function nodeConfirmed(uint256 nodeNum) external onlyRollup {
                    deliverToBridge(abi.encodePacked(CONFIRM_NODE_EVENT, nodeNum));
                }
                function nodeRejected(uint256 nodeNum) external onlyRollup {
                    deliverToBridge(abi.encodePacked(REJECT_NODE_EVENT, nodeNum));
                }
                function stakeCreated(address staker, uint256 nodeNum) external onlyRollup {
                    deliverToBridge(
                        abi.encodePacked(
                            STAKE_CREATED_EVENT,
                            uint256(uint160(bytes20(staker))),
                            nodeNum,
                            block.number
                        )
                    );
                }
                function deliverToBridge(bytes memory message) private {
                    emit InboxMessageDelivered(
                        bridge.deliverMessageToInbox(
                            ROLLUP_PROTOCOL_EVENT_TYPE,
                            msg.sender,
                            keccak256(message)
                        ),
                        message
                    );
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./INode.sol";
            import "./IRollupCore.sol";
            import "./RollupLib.sol";
            import "./INodeFactory.sol";
            import "./RollupEventBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            import "@openzeppelin/contracts/math/SafeMath.sol";
            contract RollupCore is IRollupCore {
                using SafeMath for uint256;
                // Stakers become Zombies after losing a challenge
                struct Zombie {
                    address stakerAddress;
                    uint256 latestStakedNode;
                }
                struct Staker {
                    uint256 index;
                    uint256 latestStakedNode;
                    uint256 amountStaked;
                    // currentChallenge is 0 if staker is not in a challenge
                    address currentChallenge;
                    bool isStaked;
                }
                uint256 private _latestConfirmed;
                uint256 private _firstUnresolvedNode;
                uint256 private _latestNodeCreated;
                uint256 private _lastStakeBlock;
                mapping(uint256 => INode) private _nodes;
                mapping(uint256 => bytes32) private _nodeHashes;
                address payable[] private _stakerList;
                mapping(address => Staker) public override _stakerMap;
                Zombie[] private _zombies;
                mapping(address => uint256) private _withdrawableFunds;
                /**
                 * @notice Get the address of the Node contract for the given node
                 * @param nodeNum Index of the node
                 * @return Address of the Node contract
                 */
                function getNode(uint256 nodeNum) public view override returns (INode) {
                    return _nodes[nodeNum];
                }
                /**
                 * @notice Get the address of the staker at the given index
                 * @param stakerNum Index of the staker
                 * @return Address of the staker
                 */
                function getStakerAddress(uint256 stakerNum) external view override returns (address) {
                    return _stakerList[stakerNum];
                }
                /**
                 * @notice Check whether the given staker is staked
                 * @param staker Staker address to check
                 * @return True or False for whether the staker was staked
                 */
                function isStaked(address staker) public view override returns (bool) {
                    return _stakerMap[staker].isStaked;
                }
                /**
                 * @notice Get the latest staked node of the given staker
                 * @param staker Staker address to lookup
                 * @return Latest node staked of the staker
                 */
                function latestStakedNode(address staker) public view override returns (uint256) {
                    return _stakerMap[staker].latestStakedNode;
                }
                /**
                 * @notice Get the current challenge of the given staker
                 * @param staker Staker address to lookup
                 * @return Current challenge of the staker
                 */
                function currentChallenge(address staker) public view override returns (address) {
                    return _stakerMap[staker].currentChallenge;
                }
                /**
                 * @notice Get the amount staked of the given staker
                 * @param staker Staker address to lookup
                 * @return Amount staked of the staker
                 */
                function amountStaked(address staker) public view override returns (uint256) {
                    return _stakerMap[staker].amountStaked;
                }
                /**
                 * @notice Get the original staker address of the zombie at the given index
                 * @param zombieNum Index of the zombie to lookup
                 * @return Original staker address of the zombie
                 */
                function zombieAddress(uint256 zombieNum) public view override returns (address) {
                    return _zombies[zombieNum].stakerAddress;
                }
                /**
                 * @notice Get Latest node that the given zombie at the given index is staked on
                 * @param zombieNum Index of the zombie to lookup
                 * @return Latest node that the given zombie is staked on
                 */
                function zombieLatestStakedNode(uint256 zombieNum) public view override returns (uint256) {
                    return _zombies[zombieNum].latestStakedNode;
                }
                /// @return Current number of un-removed zombies
                function zombieCount() public view override returns (uint256) {
                    return _zombies.length;
                }
                function isZombie(address staker) public view override returns (bool) {
                    for (uint256 i = 0; i < _zombies.length; i++) {
                        if (staker == _zombies[i].stakerAddress) {
                            return true;
                        }
                    }
                    return false;
                }
                /**
                 * @notice Get the amount of funds withdrawable by the given address
                 * @param owner Address to check the funds of
                 * @return Amount of funds withdrawable by owner
                 */
                function withdrawableFunds(address owner) external view override returns (uint256) {
                    return _withdrawableFunds[owner];
                }
                /**
                 * @return Index of the first unresolved node
                 * @dev If all nodes have been resolved, this will be latestNodeCreated + 1
                 */
                function firstUnresolvedNode() public view override returns (uint256) {
                    return _firstUnresolvedNode;
                }
                /// @return Index of the latest confirmed node
                function latestConfirmed() public view override returns (uint256) {
                    return _latestConfirmed;
                }
                /// @return Index of the latest rollup node created
                function latestNodeCreated() public view override returns (uint256) {
                    return _latestNodeCreated;
                }
                /// @return Ethereum block that the most recent stake was created
                function lastStakeBlock() external view override returns (uint256) {
                    return _lastStakeBlock;
                }
                /// @return Number of active stakers currently staked
                function stakerCount() public view override returns (uint256) {
                    return _stakerList.length;
                }
                /**
                 * @notice Initialize the core with an initial node
                 * @param initialNode Initial node to start the chain with
                 */
                function initializeCore(INode initialNode) internal {
                    _nodes[0] = initialNode;
                    _firstUnresolvedNode = 1;
                }
                /**
                 * @notice React to a new node being created by storing it an incrementing the latest node counter
                 * @param node Node that was newly created
                 * @param nodeHash The hash of said node
                 */
                function nodeCreated(INode node, bytes32 nodeHash) internal {
                    _latestNodeCreated++;
                    _nodes[_latestNodeCreated] = node;
                    _nodeHashes[_latestNodeCreated] = nodeHash;
                }
                /// @return Node hash as of this node number
                function getNodeHash(uint256 index) public view override returns (bytes32) {
                    return _nodeHashes[index];
                }
                /// @notice Reject the next unresolved node
                function _rejectNextNode() internal {
                    destroyNode(_firstUnresolvedNode);
                    _firstUnresolvedNode++;
                }
                /// @notice Confirm the next unresolved node
                function confirmNextNode(
                    bytes32 beforeSendAcc,
                    bytes calldata sendsData,
                    uint256[] calldata sendLengths,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount,
                    IOutbox outbox,
                    RollupEventBridge rollupEventBridge
                ) internal {
                    confirmNode(
                        _firstUnresolvedNode,
                        beforeSendAcc,
                        sendsData,
                        sendLengths,
                        afterSendCount,
                        afterLogAcc,
                        afterLogCount,
                        outbox,
                        rollupEventBridge
                    );
                }
                function confirmNode(
                    uint256 nodeNum,
                    bytes32 beforeSendAcc,
                    bytes calldata sendsData,
                    uint256[] calldata sendLengths,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount,
                    IOutbox outbox,
                    RollupEventBridge rollupEventBridge
                ) internal {
                    bytes32 afterSendAcc = RollupLib.feedAccumulator(sendsData, sendLengths, beforeSendAcc);
                    INode node = getNode(nodeNum);
                    // Authenticate data against node's confirm data pre-image
                    require(
                        node.confirmData() ==
                            RollupLib.confirmHash(
                                beforeSendAcc,
                                afterSendAcc,
                                afterLogAcc,
                                afterSendCount,
                                afterLogCount
                            ),
                        "CONFIRM_DATA"
                    );
                    // trusted external call to outbox
                    outbox.processOutgoingMessages(sendsData, sendLengths);
                    destroyNode(_latestConfirmed);
                    _latestConfirmed = nodeNum;
                    _firstUnresolvedNode = nodeNum + 1;
                    rollupEventBridge.nodeConfirmed(nodeNum);
                    emit NodeConfirmed(nodeNum, afterSendAcc, afterSendCount, afterLogAcc, afterLogCount);
                }
                /**
                 * @notice Create a new stake at latest confirmed node
                 * @param stakerAddress Address of the new staker
                 * @param depositAmount Stake amount of the new staker
                 */
                function createNewStake(address payable stakerAddress, uint256 depositAmount) internal {
                    uint256 stakerIndex = _stakerList.length;
                    _stakerList.push(stakerAddress);
                    _stakerMap[stakerAddress] = Staker(
                        stakerIndex,
                        _latestConfirmed,
                        depositAmount,
                        address(0), // new staker is not in challenge
                        true
                    );
                    _lastStakeBlock = block.number;
                    emit UserStakeUpdated(stakerAddress, 0, depositAmount);
                }
                /**
                 * @notice Check to see whether the two stakers are in the same challenge
                 * @param stakerAddress1 Address of the first staker
                 * @param stakerAddress2 Address of the second staker
                 * @return Address of the challenge that the two stakers are in
                 */
                function inChallenge(address stakerAddress1, address stakerAddress2)
                    internal
                    view
                    returns (address)
                {
                    Staker storage staker1 = _stakerMap[stakerAddress1];
                    Staker storage staker2 = _stakerMap[stakerAddress2];
                    address challenge = staker1.currentChallenge;
                    require(challenge != address(0), "NO_CHAL");
                    require(challenge == staker2.currentChallenge, "DIFF_IN_CHAL");
                    return challenge;
                }
                /**
                 * @notice Make the given staker as not being in a challenge
                 * @param stakerAddress Address of the staker to remove from a challenge
                 */
                function clearChallenge(address stakerAddress) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    staker.currentChallenge = address(0);
                }
                /**
                 * @notice Mark both the given stakers as engaged in the challenge
                 * @param staker1 Address of the first staker
                 * @param staker2 Address of the second staker
                 * @param challenge Address of the challenge both stakers are now in
                 */
                function challengeStarted(
                    address staker1,
                    address staker2,
                    address challenge
                ) internal {
                    _stakerMap[staker1].currentChallenge = challenge;
                    _stakerMap[staker2].currentChallenge = challenge;
                }
                /**
                 * @notice Add to the stake of the given staker by the given amount
                 * @param stakerAddress Address of the staker to increase the stake of
                 * @param amountAdded Amount of stake to add to the staker
                 */
                function increaseStakeBy(address stakerAddress, uint256 amountAdded) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 initialStaked = staker.amountStaked;
                    uint256 finalStaked = initialStaked.add(amountAdded);
                    staker.amountStaked = finalStaked;
                    emit UserStakeUpdated(stakerAddress, initialStaked, finalStaked);
                }
                /**
                 * @notice Reduce the stake of the given staker to the given target
                 * @param stakerAddress Address of the staker to reduce the stake of
                 * @param target Amount of stake to leave with the staker
                 * @return Amount of value released from the stake
                 */
                function reduceStakeTo(address stakerAddress, uint256 target) internal returns (uint256) {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 current = staker.amountStaked;
                    require(target <= current, "TOO_LITTLE_STAKE");
                    uint256 amountWithdrawn = current.sub(target);
                    staker.amountStaked = target;
                    increaseWithdrawableFunds(stakerAddress, amountWithdrawn);
                    emit UserStakeUpdated(stakerAddress, current, target);
                    return amountWithdrawn;
                }
                /**
                 * @notice Remove the given staker and turn them into a zombie
                 * @param stakerAddress Address of the staker to remove
                 */
                function turnIntoZombie(address stakerAddress) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    _zombies.push(Zombie(stakerAddress, staker.latestStakedNode));
                    deleteStaker(stakerAddress);
                }
                /**
                 * @notice Update the latest staked node of the zombie at the given index
                 * @param zombieNum Index of the zombie to move
                 * @param latest New latest node the zombie is staked on
                 */
                function zombieUpdateLatestStakedNode(uint256 zombieNum, uint256 latest) internal {
                    _zombies[zombieNum].latestStakedNode = latest;
                }
                /**
                 * @notice Remove the zombie at the given index
                 * @param zombieNum Index of the zombie to remove
                 */
                function removeZombie(uint256 zombieNum) internal {
                    _zombies[zombieNum] = _zombies[_zombies.length - 1];
                    _zombies.pop();
                }
                /**
                 * @notice Remove the given staker and return their stake
                 * @param stakerAddress Address of the staker withdrawing their stake
                 */
                function withdrawStaker(address stakerAddress) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 initialStaked = staker.amountStaked;
                    increaseWithdrawableFunds(stakerAddress, initialStaked);
                    deleteStaker(stakerAddress);
                    emit UserStakeUpdated(stakerAddress, initialStaked, 0);
                }
                /**
                 * @notice Advance the given staker to the given node
                 * @param stakerAddress Address of the staker adding their stake
                 * @param nodeNum Index of the node to stake on
                 */
                function stakeOnNode(
                    address stakerAddress,
                    uint256 nodeNum,
                    uint256 confirmPeriodBlocks
                ) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    INode node = _nodes[nodeNum];
                    uint256 newStakerCount = node.addStaker(stakerAddress);
                    staker.latestStakedNode = nodeNum;
                    if (newStakerCount == 1) {
                        INode parent = _nodes[node.prev()];
                        parent.newChildConfirmDeadline(block.number.add(confirmPeriodBlocks));
                    }
                }
                /**
                 * @notice Clear the withdrawable funds for the given address
                 * @param owner Address of the account to remove funds from
                 * @return Amount of funds removed from account
                 */
                function withdrawFunds(address owner) internal returns (uint256) {
                    uint256 amount = _withdrawableFunds[owner];
                    _withdrawableFunds[owner] = 0;
                    emit UserWithdrawableFundsUpdated(owner, amount, 0);
                    return amount;
                }
                /**
                 * @notice Increase the withdrawable funds for the given address
                 * @param owner Address of the account to add withdrawable funds to
                 */
                function increaseWithdrawableFunds(address owner, uint256 amount) internal {
                    uint256 initialWithdrawable = _withdrawableFunds[owner];
                    uint256 finalWithdrawable = initialWithdrawable.add(amount);
                    _withdrawableFunds[owner] = finalWithdrawable;
                    emit UserWithdrawableFundsUpdated(owner, initialWithdrawable, finalWithdrawable);
                }
                /**
                 * @notice Remove the given staker
                 * @param stakerAddress Address of the staker to remove
                 */
                function deleteStaker(address stakerAddress) private {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 stakerIndex = staker.index;
                    _stakerList[stakerIndex] = _stakerList[_stakerList.length - 1];
                    _stakerMap[_stakerList[stakerIndex]].index = stakerIndex;
                    _stakerList.pop();
                    delete _stakerMap[stakerAddress];
                }
                /**
                 * @notice Destroy the given node and clear out its address
                 * @param nodeNum Index of the node to remove
                 */
                function destroyNode(uint256 nodeNum) internal {
                    _nodes[nodeNum].destroy();
                    _nodes[nodeNum] = INode(0);
                }
                function nodeDeadline(
                    uint256 avmGasSpeedLimitPerBlock,
                    uint256 gasUsed,
                    uint256 confirmPeriodBlocks,
                    INode prevNode
                ) internal view returns (uint256 deadlineBlock) {
                    // Set deadline rounding up to the nearest block
                    uint256 checkTime =
                        gasUsed.add(avmGasSpeedLimitPerBlock.sub(1)).div(avmGasSpeedLimitPerBlock);
                    deadlineBlock = max(block.number.add(confirmPeriodBlocks), prevNode.deadlineBlock()).add(
                        checkTime
                    );
                    uint256 olderSibling = prevNode.latestChildNumber();
                    if (olderSibling != 0) {
                        deadlineBlock = max(deadlineBlock, getNode(olderSibling).deadlineBlock());
                    }
                    return deadlineBlock;
                }
                function max(uint256 a, uint256 b) internal pure returns (uint256) {
                    return a > b ? a : b;
                }
                struct StakeOnNewNodeFrame {
                    uint256 currentInboxSize;
                    INode node;
                    bytes32 executionHash;
                    INode prevNode;
                    bytes32 lastHash;
                    bool hasSibling;
                    uint256 deadlineBlock;
                    uint256 gasUsed;
                    uint256 sequencerBatchEnd;
                    bytes32 sequencerBatchAcc;
                }
                struct CreateNodeDataFrame {
                    uint256 prevNode;
                    uint256 confirmPeriodBlocks;
                    uint256 avmGasSpeedLimitPerBlock;
                    ISequencerInbox sequencerInbox;
                    RollupEventBridge rollupEventBridge;
                    INodeFactory nodeFactory;
                }
                uint8 internal constant MAX_SEND_COUNT = 100;
                function createNewNode(
                    RollupLib.Assertion memory assertion,
                    bytes32[3][2] calldata assertionBytes32Fields,
                    uint256[4][2] calldata assertionIntFields,
                    bytes calldata sequencerBatchProof,
                    CreateNodeDataFrame memory inputDataFrame,
                    bytes32 expectedNodeHash
                ) internal returns (bytes32 newNodeHash) {
                    StakeOnNewNodeFrame memory memoryFrame;
                    {
                        // validate data
                        memoryFrame.gasUsed = RollupLib.assertionGasUsed(assertion);
                        memoryFrame.prevNode = getNode(inputDataFrame.prevNode);
                        memoryFrame.currentInboxSize = inputDataFrame.sequencerInbox.messageCount();
                        // Make sure the previous state is correct against the node being built on
                        require(
                            RollupLib.stateHash(assertion.beforeState) == memoryFrame.prevNode.stateHash(),
                            "PREV_STATE_HASH"
                        );
                        // Ensure that the assertion doesn't read past the end of the current inbox
                        require(
                            assertion.afterState.inboxCount <= memoryFrame.currentInboxSize,
                            "INBOX_PAST_END"
                        );
                        // Insure inbox tip after assertion is included in a sequencer-inbox batch and return inbox acc; this gives replay protection against the state of the inbox
                        (memoryFrame.sequencerBatchEnd, memoryFrame.sequencerBatchAcc) = inputDataFrame
                            .sequencerInbox
                            .proveInboxContainsMessage(sequencerBatchProof, assertion.afterState.inboxCount);
                    }
                    {
                        memoryFrame.executionHash = RollupLib.executionHash(assertion);
                        memoryFrame.deadlineBlock = nodeDeadline(
                            inputDataFrame.avmGasSpeedLimitPerBlock,
                            memoryFrame.gasUsed,
                            inputDataFrame.confirmPeriodBlocks,
                            memoryFrame.prevNode
                        );
                        memoryFrame.hasSibling = memoryFrame.prevNode.latestChildNumber() > 0;
                        // here we don't use ternacy operator to remain compatible with slither
                        if (memoryFrame.hasSibling) {
                            memoryFrame.lastHash = getNodeHash(memoryFrame.prevNode.latestChildNumber());
                        } else {
                            memoryFrame.lastHash = getNodeHash(inputDataFrame.prevNode);
                        }
                        memoryFrame.node = INode(
                            inputDataFrame.nodeFactory.createNode(
                                RollupLib.stateHash(assertion.afterState),
                                RollupLib.challengeRoot(assertion, memoryFrame.executionHash, block.number),
                                RollupLib.confirmHash(assertion),
                                inputDataFrame.prevNode,
                                memoryFrame.deadlineBlock
                            )
                        );
                    }
                    {
                        uint256 nodeNum = latestNodeCreated() + 1;
                        memoryFrame.prevNode.childCreated(nodeNum);
                        newNodeHash = RollupLib.nodeHash(
                            memoryFrame.hasSibling,
                            memoryFrame.lastHash,
                            memoryFrame.executionHash,
                            memoryFrame.sequencerBatchAcc
                        );
                        require(newNodeHash == expectedNodeHash, "UNEXPECTED_NODE_HASH");
                        nodeCreated(memoryFrame.node, newNodeHash);
                        inputDataFrame.rollupEventBridge.nodeCreated(
                            nodeNum,
                            inputDataFrame.prevNode,
                            memoryFrame.deadlineBlock,
                            msg.sender
                        );
                    }
                    emit NodeCreated(
                        latestNodeCreated(),
                        getNodeHash(inputDataFrame.prevNode),
                        newNodeHash,
                        memoryFrame.executionHash,
                        memoryFrame.currentInboxSize,
                        memoryFrame.sequencerBatchEnd,
                        memoryFrame.sequencerBatchAcc,
                        assertionBytes32Fields,
                        assertionIntFields
                    );
                    return newNodeHash;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../challenge/ChallengeLib.sol";
            import "./INode.sol";
            import "@openzeppelin/contracts/math/SafeMath.sol";
            library RollupLib {
                using SafeMath for uint256;
                struct Config {
                    bytes32 machineHash;
                    uint256 confirmPeriodBlocks;
                    uint256 extraChallengeTimeBlocks;
                    uint256 avmGasSpeedLimitPerBlock;
                    uint256 baseStake;
                    address stakeToken;
                    address owner;
                    address sequencer;
                    uint256 sequencerDelayBlocks;
                    uint256 sequencerDelaySeconds;
                    bytes extraConfig;
                }
                struct ExecutionState {
                    uint256 gasUsed;
                    bytes32 machineHash;
                    uint256 inboxCount;
                    uint256 sendCount;
                    uint256 logCount;
                    bytes32 sendAcc;
                    bytes32 logAcc;
                    uint256 proposedBlock;
                    uint256 inboxMaxCount;
                }
                function stateHash(ExecutionState memory execState) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                execState.gasUsed,
                                execState.machineHash,
                                execState.inboxCount,
                                execState.sendCount,
                                execState.logCount,
                                execState.sendAcc,
                                execState.logAcc,
                                execState.proposedBlock,
                                execState.inboxMaxCount
                            )
                        );
                }
                struct Assertion {
                    ExecutionState beforeState;
                    ExecutionState afterState;
                }
                function decodeExecutionState(
                    bytes32[3] memory bytes32Fields,
                    uint256[4] memory intFields,
                    uint256 proposedBlock,
                    uint256 inboxMaxCount
                ) internal pure returns (ExecutionState memory) {
                    return
                        ExecutionState(
                            intFields[0],
                            bytes32Fields[0],
                            intFields[1],
                            intFields[2],
                            intFields[3],
                            bytes32Fields[1],
                            bytes32Fields[2],
                            proposedBlock,
                            inboxMaxCount
                        );
                }
                function decodeAssertion(
                    bytes32[3][2] memory bytes32Fields,
                    uint256[4][2] memory intFields,
                    uint256 beforeProposedBlock,
                    uint256 beforeInboxMaxCount,
                    uint256 inboxMaxCount
                ) internal view returns (Assertion memory) {
                    return
                        Assertion(
                            decodeExecutionState(
                                bytes32Fields[0],
                                intFields[0],
                                beforeProposedBlock,
                                beforeInboxMaxCount
                            ),
                            decodeExecutionState(bytes32Fields[1], intFields[1], block.number, inboxMaxCount)
                        );
                }
                function executionStateChallengeHash(ExecutionState memory state)
                    internal
                    pure
                    returns (bytes32)
                {
                    return
                        ChallengeLib.assertionHash(
                            state.gasUsed,
                            ChallengeLib.assertionRestHash(
                                state.inboxCount,
                                state.machineHash,
                                state.sendAcc,
                                state.sendCount,
                                state.logAcc,
                                state.logCount
                            )
                        );
                }
                function executionHash(Assertion memory assertion) internal pure returns (bytes32) {
                    return
                        ChallengeLib.bisectionChunkHash(
                            assertion.beforeState.gasUsed,
                            assertion.afterState.gasUsed - assertion.beforeState.gasUsed,
                            RollupLib.executionStateChallengeHash(assertion.beforeState),
                            RollupLib.executionStateChallengeHash(assertion.afterState)
                        );
                }
                function assertionGasUsed(RollupLib.Assertion memory assertion)
                    internal
                    pure
                    returns (uint256)
                {
                    return assertion.afterState.gasUsed.sub(assertion.beforeState.gasUsed);
                }
                function challengeRoot(
                    Assertion memory assertion,
                    bytes32 assertionExecHash,
                    uint256 blockProposed
                ) internal pure returns (bytes32) {
                    return challengeRootHash(assertionExecHash, blockProposed, assertion.afterState.inboxCount);
                }
                function challengeRootHash(
                    bytes32 execution,
                    uint256 proposedTime,
                    uint256 maxMessageCount
                ) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(execution, proposedTime, maxMessageCount));
                }
                function confirmHash(Assertion memory assertion) internal pure returns (bytes32) {
                    return
                        confirmHash(
                            assertion.beforeState.sendAcc,
                            assertion.afterState.sendAcc,
                            assertion.afterState.logAcc,
                            assertion.afterState.sendCount,
                            assertion.afterState.logCount
                        );
                }
                function confirmHash(
                    bytes32 beforeSendAcc,
                    bytes32 afterSendAcc,
                    bytes32 afterLogAcc,
                    uint256 afterSendCount,
                    uint256 afterLogCount
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                beforeSendAcc,
                                afterSendAcc,
                                afterSendCount,
                                afterLogAcc,
                                afterLogCount
                            )
                        );
                }
                function feedAccumulator(
                    bytes memory messageData,
                    uint256[] memory messageLengths,
                    bytes32 beforeAcc
                ) internal pure returns (bytes32) {
                    uint256 offset = 0;
                    uint256 messageCount = messageLengths.length;
                    uint256 dataLength = messageData.length;
                    bytes32 messageAcc = beforeAcc;
                    for (uint256 i = 0; i < messageCount; i++) {
                        uint256 messageLength = messageLengths[i];
                        require(offset + messageLength <= dataLength, "DATA_OVERRUN");
                        bytes32 messageHash;
                        assembly {
                            messageHash := keccak256(add(messageData, add(offset, 32)), messageLength)
                        }
                        messageAcc = keccak256(abi.encodePacked(messageAcc, messageHash));
                        offset += messageLength;
                    }
                    require(offset == dataLength, "DATA_LENGTH");
                    return messageAcc;
                }
                function nodeHash(
                    bool hasSibling,
                    bytes32 lastHash,
                    bytes32 assertionExecHash,
                    bytes32 inboxAcc
                ) internal pure returns (bytes32) {
                    uint8 hasSiblingInt = hasSibling ? 1 : 0;
                    return keccak256(abi.encodePacked(hasSiblingInt, lastHash, assertionExecHash, inboxAcc));
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface INode {
                function initialize(
                    address _rollup,
                    bytes32 _stateHash,
                    bytes32 _challengeHash,
                    bytes32 _confirmData,
                    uint256 _prev,
                    uint256 _deadlineBlock
                ) external;
                function destroy() external;
                function addStaker(address staker) external returns (uint256);
                function removeStaker(address staker) external;
                function childCreated(uint256) external;
                function newChildConfirmDeadline(uint256 deadline) external;
                function stateHash() external view returns (bytes32);
                function challengeHash() external view returns (bytes32);
                function confirmData() external view returns (bytes32);
                function prev() external view returns (uint256);
                function deadlineBlock() external view returns (uint256);
                function noChildConfirmedBeforeBlock() external view returns (uint256);
                function stakerCount() external view returns (uint256);
                function stakers(address staker) external view returns (bool);
                function firstChildBlock() external view returns (uint256);
                function latestChildNumber() external view returns (uint256);
                function requirePastDeadline() external view;
                function requirePastChildConfirmDeadline() external view;
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface INodeFactory {
                function createNode(
                    bytes32 _stateHash,
                    bytes32 _challengeHash,
                    bytes32 _confirmData,
                    uint256 _prev,
                    uint256 _deadlineBlock
                ) external returns (address);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            import "../arch/IOneStepProof.sol";
            interface IChallenge {
                function initializeChallenge(
                    IOneStepProof[] calldata _executors,
                    address _resultReceiver,
                    bytes32 _executionHash,
                    uint256 _maxMessageCount,
                    address _asserter,
                    address _challenger,
                    uint256 _asserterTimeLeft,
                    uint256 _challengerTimeLeft,
                    ISequencerInbox _sequencerBridge,
                    IBridge _delayedBridge
                ) external;
                function currentResponderTimeLeft() external view returns (uint256);
                function lastMoveBlock() external view returns (uint256);
                function timeout() external;
                function asserter() external view returns (address);
                function challenger() external view returns (address);
                function clearChallenge() external;
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            interface IChallengeFactory {
                function createChallenge(
                    address _resultReceiver,
                    bytes32 _executionHash,
                    uint256 _maxMessageCount,
                    address _asserter,
                    address _challenger,
                    uint256 _asserterTimeLeft,
                    uint256 _challengerTimeLeft,
                    ISequencerInbox _sequencerBridge,
                    IBridge _delayedBridge
                ) external returns (address);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface IOutbox {
                event OutboxEntryCreated(
                    uint256 indexed batchNum,
                    uint256 outboxEntryIndex,
                    bytes32 outputRoot,
                    uint256 numInBatch
                );
                event OutBoxTransactionExecuted(
                    address indexed destAddr,
                    address indexed l2Sender,
                    uint256 indexed outboxEntryIndex,
                    uint256 transactionIndex
                );
                function l2ToL1Sender() external view returns (address);
                function l2ToL1Block() external view returns (uint256);
                function l2ToL1EthBlock() external view returns (uint256);
                function l2ToL1Timestamp() external view returns (uint256);
                function l2ToL1BatchNum() external view returns (uint256);
                function l2ToL1OutputId() external view returns (bytes32);
                function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths)
                    external;
                function outboxEntryExists(uint256 batchNum) external view returns (bool);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library ProxyUtil {
                function getProxyAdmin() internal view returns (address admin) {
                    // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/proxy/TransparentUpgradeableProxy.sol#L48
                    // Storage slot with the admin of the proxy contract.
                    // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                    bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                    assembly {
                        admin := sload(slot)
                    }
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../INode.sol";
            import "../../bridge/interfaces/IOutbox.sol";
            interface IRollupUser {
                function initialize(address _stakeToken) external;
                function completeChallenge(address winningStaker, address losingStaker) external;
                function returnOldDeposit(address stakerAddress) external;
                function requireUnresolved(uint256 nodeNum) external view;
                function requireUnresolvedExists() external view;
                function countStakedZombies(INode node) external view returns (uint256);
            }
            interface IRollupAdmin {
                event OwnerFunctionCalled(uint256 indexed id);
                /**
                 * @notice Add a contract authorized to put messages into this rollup's inbox
                 * @param _outbox Outbox contract to add
                 */
                function setOutbox(IOutbox _outbox) external;
                /**
                 * @notice Disable an old outbox from interacting with the bridge
                 * @param _outbox Outbox contract to remove
                 */
                function removeOldOutbox(address _outbox) external;
                /**
                 * @notice Enable or disable an inbox contract
                 * @param _inbox Inbox contract to add or remove
                 * @param _enabled New status of inbox
                 */
                function setInbox(address _inbox, bool _enabled) external;
                /**
                 * @notice Pause interaction with the rollup contract
                 */
                function pause() external;
                /**
                 * @notice Resume interaction with the rollup contract
                 */
                function resume() external;
                /**
                 * @notice Set the addresses of rollup logic facets called
                 * @param newAdminFacet address of logic that owner of rollup calls
                 * @param newUserFacet ddress of logic that user of rollup calls
                 */
                function setFacets(address newAdminFacet, address newUserFacet) external;
                /**
                 * @notice Set the addresses of the validator whitelist
                 * @dev It is expected that both arrays are same length, and validator at
                 * position i corresponds to the value at position i
                 * @param _validator addresses to set in the whitelist
                 * @param _val value to set in the whitelist for corresponding address
                 */
                function setValidator(address[] memory _validator, bool[] memory _val) external;
                /**
                 * @notice Set a new owner address for the rollup
                 * @param newOwner address of new rollup owner
                 */
                function setOwner(address newOwner) external;
                /**
                 * @notice Set minimum assertion period for the rollup
                 * @param newPeriod new minimum period for assertions
                 */
                function setMinimumAssertionPeriod(uint256 newPeriod) external;
                /**
                 * @notice Set number of blocks until a node is considered confirmed
                 * @param newConfirmPeriod new number of blocks until a node is confirmed
                 */
                function setConfirmPeriodBlocks(uint256 newConfirmPeriod) external;
                /**
                 * @notice Set number of extra blocks after a challenge
                 * @param newExtraTimeBlocks new number of blocks
                 */
                function setExtraChallengeTimeBlocks(uint256 newExtraTimeBlocks) external;
                /**
                 * @notice Set speed limit per block
                 * @param newAvmGasSpeedLimitPerBlock maximum avmgas to be used per block
                 */
                function setAvmGasSpeedLimitPerBlock(uint256 newAvmGasSpeedLimitPerBlock) external;
                /**
                 * @notice Set base stake required for an assertion
                 * @param newBaseStake maximum avmgas to be used per block
                 */
                function setBaseStake(uint256 newBaseStake) external;
                /**
                 * @notice Set the token used for stake, where address(0) == eth
                 * @dev Before changing the base stake token, you might need to change the
                 * implementation of the Rollup User facet!
                 * @param newStakeToken address of token used for staking
                 */
                function setStakeToken(address newStakeToken) external;
                /**
                 * @notice Set max delay for sequencer inbox
                 * @param newSequencerInboxMaxDelayBlocks max number of blocks
                 * @param newSequencerInboxMaxDelaySeconds max number of seconds
                 */
                function setSequencerInboxMaxDelay(
                    uint256 newSequencerInboxMaxDelayBlocks,
                    uint256 newSequencerInboxMaxDelaySeconds
                ) external;
                /**
                 * @notice Set execution bisection degree
                 * @param newChallengeExecutionBisectionDegree execution bisection degree
                 */
                function setChallengeExecutionBisectionDegree(uint256 newChallengeExecutionBisectionDegree)
                    external;
                /**
                 * @notice Updates a whitelist address for its consumers
                 * @dev setting the newWhitelist to address(0) disables it for consumers
                 * @param whitelist old whitelist to be deprecated
                 * @param newWhitelist new whitelist to be used
                 * @param targets whitelist consumers to be triggered
                 */
                function updateWhitelistConsumers(
                    address whitelist,
                    address newWhitelist,
                    address[] memory targets
                ) external;
                /**
                 * @notice Updates a whitelist's entries
                 * @dev user at position i will be assigned value i
                 * @param whitelist whitelist to be updated
                 * @param user users to be updated in the whitelist
                 * @param val if user is or not allowed in the whitelist
                 */
                function setWhitelistEntries(
                    address whitelist,
                    address[] memory user,
                    bool[] memory val
                ) external;
                /**
                 * @notice Updates whether an address is a sequencer at the sequencer inbox
                 * @param newSequencer address to be modified
                 * @param isSequencer whether this address should be authorized as a sequencer
                 */
                function setIsSequencer(address newSequencer, bool isSequencer) external;
                /**
                 * @notice Upgrades the implementation of a beacon controlled by the rollup
                 * @param beacon address of beacon to be upgraded
                 * @param newImplementation new address of implementation
                 */
                function upgradeBeacon(address beacon, address newImplementation) external;
                function forceResolveChallenge(address[] memory stackerA, address[] memory stackerB) external;
                function forceRefundStaker(address[] memory stacker) external;
                function forceCreateNode(
                    bytes32 expectedNodeHash,
                    bytes32[3][2] calldata assertionBytes32Fields,
                    uint256[4][2] calldata assertionIntFields,
                    bytes calldata sequencerBatchProof,
                    uint256 beforeProposedBlock,
                    uint256 beforeInboxMaxCount,
                    uint256 prevNode
                ) external;
                function forceConfirmNode(
                    uint256 nodeNum,
                    bytes32 beforeSendAcc,
                    bytes calldata sendsData,
                    uint256[] calldata sendLengths,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount
                ) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /*
             * @dev Provides information about the current execution context, including the
             * sender of the transaction and its data. While these are generally available
             * via msg.sender and msg.data, they should not be accessed in such a direct
             * manner, since when dealing with GSN meta-transactions the account sending and
             * paying for execution may not be the actual sender (as far as an application
             * is concerned).
             *
             * This contract is only required for intermediate, library-like contracts.
             */
            abstract contract Context {
                function _msgSender() internal view virtual returns (address payable) {
                    return msg.sender;
                }
                function _msgData() internal view virtual returns (bytes memory) {
                    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                    return msg.data;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface IMessageProvider {
                event InboxMessageDelivered(uint256 indexed messageNum, bytes data);
                event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./INode.sol";
            interface IRollupCore {
                function _stakerMap(address stakerAddress)
                    external
                    view
                    returns (
                        uint256,
                        uint256,
                        uint256,
                        address,
                        bool
                    );
                event RollupCreated(bytes32 machineHash);
                event NodeCreated(
                    uint256 indexed nodeNum,
                    bytes32 indexed parentNodeHash,
                    bytes32 nodeHash,
                    bytes32 executionHash,
                    uint256 inboxMaxCount,
                    uint256 afterInboxBatchEndCount,
                    bytes32 afterInboxBatchAcc,
                    bytes32[3][2] assertionBytes32Fields,
                    uint256[4][2] assertionIntFields
                );
                event NodeConfirmed(
                    uint256 indexed nodeNum,
                    bytes32 afterSendAcc,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount
                );
                event NodeRejected(uint256 indexed nodeNum);
                event RollupChallengeStarted(
                    address indexed challengeContract,
                    address asserter,
                    address challenger,
                    uint256 challengedNode
                );
                event UserStakeUpdated(address indexed user, uint256 initialBalance, uint256 finalBalance);
                event UserWithdrawableFundsUpdated(
                    address indexed user,
                    uint256 initialBalance,
                    uint256 finalBalance
                );
                function getNode(uint256 nodeNum) external view returns (INode);
                /**
                 * @notice Get the address of the staker at the given index
                 * @param stakerNum Index of the staker
                 * @return Address of the staker
                 */
                function getStakerAddress(uint256 stakerNum) external view returns (address);
                /**
                 * @notice Check whether the given staker is staked
                 * @param staker Staker address to check
                 * @return True or False for whether the staker was staked
                 */
                function isStaked(address staker) external view returns (bool);
                /**
                 * @notice Get the latest staked node of the given staker
                 * @param staker Staker address to lookup
                 * @return Latest node staked of the staker
                 */
                function latestStakedNode(address staker) external view returns (uint256);
                /**
                 * @notice Get the current challenge of the given staker
                 * @param staker Staker address to lookup
                 * @return Current challenge of the staker
                 */
                function currentChallenge(address staker) external view returns (address);
                /**
                 * @notice Get the amount staked of the given staker
                 * @param staker Staker address to lookup
                 * @return Amount staked of the staker
                 */
                function amountStaked(address staker) external view returns (uint256);
                /**
                 * @notice Get the original staker address of the zombie at the given index
                 * @param zombieNum Index of the zombie to lookup
                 * @return Original staker address of the zombie
                 */
                function zombieAddress(uint256 zombieNum) external view returns (address);
                /**
                 * @notice Get Latest node that the given zombie at the given index is staked on
                 * @param zombieNum Index of the zombie to lookup
                 * @return Latest node that the given zombie is staked on
                 */
                function zombieLatestStakedNode(uint256 zombieNum) external view returns (uint256);
                /// @return Current number of un-removed zombies
                function zombieCount() external view returns (uint256);
                function isZombie(address staker) external view returns (bool);
                /**
                 * @notice Get the amount of funds withdrawable by the given address
                 * @param owner Address to check the funds of
                 * @return Amount of funds withdrawable by owner
                 */
                function withdrawableFunds(address owner) external view returns (uint256);
                /**
                 * @return Index of the first unresolved node
                 * @dev If all nodes have been resolved, this will be latestNodeCreated + 1
                 */
                function firstUnresolvedNode() external view returns (uint256);
                /// @return Index of the latest confirmed node
                function latestConfirmed() external view returns (uint256);
                /// @return Index of the latest rollup node created
                function latestNodeCreated() external view returns (uint256);
                /// @return Ethereum block that the most recent stake was created
                function lastStakeBlock() external view returns (uint256);
                /// @return Number of active stakers currently staked
                function stakerCount() external view returns (uint256);
                /// @return Node hash as of this node number
                function getNodeHash(uint256 index) external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev Wrappers over Solidity's arithmetic operations with added overflow
             * checks.
             *
             * Arithmetic operations in Solidity wrap on overflow. This can easily result
             * in bugs, because programmers usually assume that an overflow raises an
             * error, which is the standard behavior in high level programming languages.
             * `SafeMath` restores this intuition by reverting the transaction when an
             * operation overflows.
             *
             * Using this library instead of the unchecked operations eliminates an entire
             * class of bugs, so it's recommended to use it always.
             */
            library SafeMath {
                /**
                 * @dev Returns the addition of two unsigned integers, with an overflow flag.
                 *
                 * _Available since v3.4._
                 */
                function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    uint256 c = a + b;
                    if (c < a) return (false, 0);
                    return (true, c);
                }
                /**
                 * @dev Returns the substraction of two unsigned integers, with an overflow flag.
                 *
                 * _Available since v3.4._
                 */
                function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    if (b > a) return (false, 0);
                    return (true, a - b);
                }
                /**
                 * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
                 *
                 * _Available since v3.4._
                 */
                function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                    // benefit is lost if 'b' is also tested.
                    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                    if (a == 0) return (true, 0);
                    uint256 c = a * b;
                    if (c / a != b) return (false, 0);
                    return (true, c);
                }
                /**
                 * @dev Returns the division of two unsigned integers, with a division by zero flag.
                 *
                 * _Available since v3.4._
                 */
                function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    if (b == 0) return (false, 0);
                    return (true, a / b);
                }
                /**
                 * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
                 *
                 * _Available since v3.4._
                 */
                function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    if (b == 0) return (false, 0);
                    return (true, a % b);
                }
                /**
                 * @dev Returns the addition of two unsigned integers, reverting on
                 * overflow.
                 *
                 * Counterpart to Solidity's `+` operator.
                 *
                 * Requirements:
                 *
                 * - Addition cannot overflow.
                 */
                function add(uint256 a, uint256 b) internal pure returns (uint256) {
                    uint256 c = a + b;
                    require(c >= a, "SafeMath: addition overflow");
                    return c;
                }
                /**
                 * @dev Returns the subtraction of two unsigned integers, reverting on
                 * overflow (when the result is negative).
                 *
                 * Counterpart to Solidity's `-` operator.
                 *
                 * Requirements:
                 *
                 * - Subtraction cannot overflow.
                 */
                function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                    require(b <= a, "SafeMath: subtraction overflow");
                    return a - b;
                }
                /**
                 * @dev Returns the multiplication of two unsigned integers, reverting on
                 * overflow.
                 *
                 * Counterpart to Solidity's `*` operator.
                 *
                 * Requirements:
                 *
                 * - Multiplication cannot overflow.
                 */
                function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                    if (a == 0) return 0;
                    uint256 c = a * b;
                    require(c / a == b, "SafeMath: multiplication overflow");
                    return c;
                }
                /**
                 * @dev Returns the integer division of two unsigned integers, reverting on
                 * division by zero. The result is rounded towards zero.
                 *
                 * Counterpart to Solidity's `/` operator. Note: this function uses a
                 * `revert` opcode (which leaves remaining gas untouched) while Solidity
                 * uses an invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function div(uint256 a, uint256 b) internal pure returns (uint256) {
                    require(b > 0, "SafeMath: division by zero");
                    return a / b;
                }
                /**
                 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                 * reverting when dividing by zero.
                 *
                 * Counterpart to Solidity's `%` operator. This function uses a `revert`
                 * opcode (which leaves remaining gas untouched) while Solidity uses an
                 * invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                    require(b > 0, "SafeMath: modulo by zero");
                    return a % b;
                }
                /**
                 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
                 * overflow (when the result is negative).
                 *
                 * CAUTION: This function is deprecated because it requires allocating memory for the error
                 * message unnecessarily. For custom revert reasons use {trySub}.
                 *
                 * Counterpart to Solidity's `-` operator.
                 *
                 * Requirements:
                 *
                 * - Subtraction cannot overflow.
                 */
                function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                    require(b <= a, errorMessage);
                    return a - b;
                }
                /**
                 * @dev Returns the integer division of two unsigned integers, reverting with custom message on
                 * division by zero. The result is rounded towards zero.
                 *
                 * CAUTION: This function is deprecated because it requires allocating memory for the error
                 * message unnecessarily. For custom revert reasons use {tryDiv}.
                 *
                 * Counterpart to Solidity's `/` operator. Note: this function uses a
                 * `revert` opcode (which leaves remaining gas untouched) while Solidity
                 * uses an invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                    require(b > 0, errorMessage);
                    return a / b;
                }
                /**
                 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                 * reverting with custom message when dividing by zero.
                 *
                 * CAUTION: This function is deprecated because it requires allocating memory for the error
                 * message unnecessarily. For custom revert reasons use {tryMod}.
                 *
                 * Counterpart to Solidity's `%` operator. This function uses a `revert`
                 * opcode (which leaves remaining gas untouched) while Solidity uses an
                 * invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                    require(b > 0, errorMessage);
                    return a % b;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../libraries/MerkleLib.sol";
            import "@openzeppelin/contracts/math/SafeMath.sol";
            library ChallengeLib {
                using SafeMath for uint256;
                function firstSegmentSize(uint256 totalCount, uint256 bisectionCount)
                    internal
                    pure
                    returns (uint256)
                {
                    return totalCount / bisectionCount + (totalCount % bisectionCount);
                }
                function otherSegmentSize(uint256 totalCount, uint256 bisectionCount)
                    internal
                    pure
                    returns (uint256)
                {
                    return totalCount / bisectionCount;
                }
                function bisectionChunkHash(
                    uint256 _segmentStart,
                    uint256 _segmentLength,
                    bytes32 _startHash,
                    bytes32 _endHash
                ) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(_segmentStart, _segmentLength, _startHash, _endHash));
                }
                function assertionHash(uint256 _avmGasUsed, bytes32 _restHash) internal pure returns (bytes32) {
                    // Note: make sure this doesn't return Challenge.UNREACHABLE_ASSERTION (currently 0)
                    return keccak256(abi.encodePacked(_avmGasUsed, _restHash));
                }
                function assertionRestHash(
                    uint256 _totalMessagesRead,
                    bytes32 _machineState,
                    bytes32 _sendAcc,
                    uint256 _sendCount,
                    bytes32 _logAcc,
                    uint256 _logCount
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                _totalMessagesRead,
                                _machineState,
                                _sendAcc,
                                _sendCount,
                                _logAcc,
                                _logCount
                            )
                        );
                }
                function updatedBisectionRoot(
                    bytes32[] memory _chainHashes,
                    uint256 _challengedSegmentStart,
                    uint256 _challengedSegmentLength
                ) internal pure returns (bytes32) {
                    uint256 bisectionCount = _chainHashes.length - 1;
                    bytes32[] memory hashes = new bytes32[](bisectionCount);
                    uint256 chunkSize = ChallengeLib.firstSegmentSize(_challengedSegmentLength, bisectionCount);
                    uint256 segmentStart = _challengedSegmentStart;
                    hashes[0] = ChallengeLib.bisectionChunkHash(
                        segmentStart,
                        chunkSize,
                        _chainHashes[0],
                        _chainHashes[1]
                    );
                    segmentStart = segmentStart.add(chunkSize);
                    chunkSize = ChallengeLib.otherSegmentSize(_challengedSegmentLength, bisectionCount);
                    for (uint256 i = 1; i < bisectionCount; i++) {
                        hashes[i] = ChallengeLib.bisectionChunkHash(
                            segmentStart,
                            chunkSize,
                            _chainHashes[i],
                            _chainHashes[i + 1]
                        );
                        segmentStart = segmentStart.add(chunkSize);
                    }
                    return MerkleLib.generateRoot(hashes);
                }
                function verifySegmentProof(
                    bytes32 challengeState,
                    bytes32 item,
                    bytes32[] calldata _merkleNodes,
                    uint256 _merkleRoute
                ) internal pure returns (bool) {
                    return challengeState == MerkleLib.calculateRoot(_merkleNodes, _merkleRoute, item);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library MerkleLib {
                function generateRoot(bytes32[] memory _hashes) internal pure returns (bytes32) {
                    bytes32[] memory prevLayer = _hashes;
                    while (prevLayer.length > 1) {
                        bytes32[] memory nextLayer = new bytes32[]((prevLayer.length + 1) / 2);
                        for (uint256 i = 0; i < nextLayer.length; i++) {
                            if (2 * i + 1 < prevLayer.length) {
                                nextLayer[i] = keccak256(
                                    abi.encodePacked(prevLayer[2 * i], prevLayer[2 * i + 1])
                                );
                            } else {
                                nextLayer[i] = prevLayer[2 * i];
                            }
                        }
                        prevLayer = nextLayer;
                    }
                    return prevLayer[0];
                }
                function calculateRoot(
                    bytes32[] memory nodes,
                    uint256 route,
                    bytes32 item
                ) internal pure returns (bytes32) {
                    uint256 proofItems = nodes.length;
                    require(proofItems <= 256);
                    bytes32 h = item;
                    for (uint256 i = 0; i < proofItems; i++) {
                        if (route % 2 == 0) {
                            h = keccak256(abi.encodePacked(nodes[i], h));
                        } else {
                            h = keccak256(abi.encodePacked(h, nodes[i]));
                        }
                        route /= 2;
                    }
                    return h;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2020, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            interface IOneStepProof {
                // Bridges is sequencer bridge then delayed bridge
                function executeStep(
                    address[2] calldata bridges,
                    uint256 initialMessagesRead,
                    bytes32[2] calldata accs,
                    bytes calldata proof,
                    bytes calldata bproof
                )
                    external
                    view
                    returns (
                        uint64 gas,
                        uint256 afterMessagesRead,
                        bytes32[4] memory fields
                    );
                function executeStepDebug(
                    address[2] calldata bridges,
                    uint256 initialMessagesRead,
                    bytes32[2] calldata accs,
                    bytes calldata proof,
                    bytes calldata bproof
                ) external view returns (string memory startMachine, string memory afterMachine);
            }
            

            File 4 of 5: TransparentUpgradeableProxy
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 { revert(0, returndatasize()) }
                        default { return(0, returndatasize()) }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overriden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./UpgradeableProxy.sol";
            /**
             * @dev This contract implements a proxy that is upgradeable by an admin.
             *
             * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
             * clashing], which can potentially be used in an attack, this contract uses the
             * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
             * things that go hand in hand:
             *
             * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
             * that call matches one of the admin functions exposed by the proxy itself.
             * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
             * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
             * "admin cannot fallback to proxy target".
             *
             * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
             * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
             * to sudden errors when trying to call a function from the proxy implementation.
             *
             * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
             * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
             */
            contract TransparentUpgradeableProxy is UpgradeableProxy {
                /**
                 * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
                 * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
                 */
                constructor(address _logic, address admin_, bytes memory _data) public payable UpgradeableProxy(_logic, _data) {
                    assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
                    _setAdmin(admin_);
                }
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
                 */
                modifier ifAdmin() {
                    if (msg.sender == _admin()) {
                        _;
                    } else {
                        _fallback();
                    }
                }
                /**
                 * @dev Returns the current admin.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
                 */
                function admin() external ifAdmin returns (address admin_) {
                    admin_ = _admin();
                }
                /**
                 * @dev Returns the current implementation.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
                 */
                function implementation() external ifAdmin returns (address implementation_) {
                    implementation_ = _implementation();
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
                 */
                function changeAdmin(address newAdmin) external virtual ifAdmin {
                    require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address");
                    emit AdminChanged(_admin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev Upgrade the implementation of the proxy.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
                 */
                function upgradeTo(address newImplementation) external virtual ifAdmin {
                    _upgradeTo(newImplementation);
                }
                /**
                 * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
                 * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
                 * proxied contract.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
                 */
                function upgradeToAndCall(address newImplementation, bytes calldata data) external payable virtual ifAdmin {
                    _upgradeTo(newImplementation);
                    Address.functionDelegateCall(newImplementation, data);
                }
                /**
                 * @dev Returns the current admin.
                 */
                function _admin() internal view virtual returns (address adm) {
                    bytes32 slot = _ADMIN_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        adm := sload(slot)
                    }
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    bytes32 slot = _ADMIN_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        sstore(slot, newAdmin)
                    }
                }
                /**
                 * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
                 */
                function _beforeFallback() internal virtual override {
                    require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                    super._beforeFallback();
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./Proxy.sol";
            import "../utils/Address.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             *
             * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
             * {TransparentUpgradeableProxy}.
             */
            contract UpgradeableProxy is Proxy {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                 * function call, and allows initializating the storage of the proxy like a Solidity constructor.
                 */
                constructor(address _logic, bytes memory _data) public payable {
                    assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
                    _setImplementation(_logic);
                    if(_data.length > 0) {
                        Address.functionDelegateCall(_logic, _data);
                    }
                }
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Returns the current implementation address.
                 */
                function _implementation() internal view virtual override returns (address impl) {
                    bytes32 slot = _IMPLEMENTATION_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        impl := sload(slot)
                    }
                }
                /**
                 * @dev Upgrades the proxy to a new implementation.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal virtual {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract");
                    bytes32 slot = _IMPLEMENTATION_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        sstore(slot, newImplementation)
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.2 <0.8.0;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize, which returns 0 for contracts in
                    // construction, since the code is only stored at the end of the
                    // constructor execution.
                    uint256 size;
                    // solhint-disable-next-line no-inline-assembly
                    assembly { size := extcodesize(account) }
                    return size > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                    (bool success, ) = recipient.call{ value: amount }("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain`call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                  return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.call{ value: value }(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    require(isContract(target), "Address: delegate call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            // solhint-disable-next-line no-inline-assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }
            

            File 5 of 5: Bridge
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./Inbox.sol";
            import "./Outbox.sol";
            import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
            import "@openzeppelin/contracts/utils/Address.sol";
            import "./interfaces/IBridge.sol";
            contract Bridge is OwnableUpgradeable, IBridge {
                using Address for address;
                struct InOutInfo {
                    uint256 index;
                    bool allowed;
                }
                mapping(address => InOutInfo) private allowedInboxesMap;
                mapping(address => InOutInfo) private allowedOutboxesMap;
                address[] public allowedInboxList;
                address[] public allowedOutboxList;
                address public override activeOutbox;
                // Accumulator for delayed inbox; tail represents hash of the current state; each element represents the inclusion of a new message.
                bytes32[] public override inboxAccs;
                function initialize() external initializer {
                    __Ownable_init();
                }
                function allowedInboxes(address inbox) external view override returns (bool) {
                    return allowedInboxesMap[inbox].allowed;
                }
                function allowedOutboxes(address outbox) external view override returns (bool) {
                    return allowedOutboxesMap[outbox].allowed;
                }
                function deliverMessageToInbox(
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                ) external payable override returns (uint256) {
                    require(allowedInboxesMap[msg.sender].allowed, "NOT_FROM_INBOX");
                    uint256 count = inboxAccs.length;
                    bytes32 messageHash =
                        Messages.messageHash(
                            kind,
                            sender,
                            block.number,
                            block.timestamp, // solhint-disable-line not-rely-on-time
                            count,
                            tx.gasprice,
                            messageDataHash
                        );
                    bytes32 prevAcc = 0;
                    if (count > 0) {
                        prevAcc = inboxAccs[count - 1];
                    }
                    inboxAccs.push(Messages.addMessageToInbox(prevAcc, messageHash));
                    emit MessageDelivered(count, prevAcc, msg.sender, kind, sender, messageDataHash);
                    return count;
                }
                function executeCall(
                    address destAddr,
                    uint256 amount,
                    bytes calldata data
                ) external override returns (bool success, bytes memory returnData) {
                    require(allowedOutboxesMap[msg.sender].allowed, "NOT_FROM_OUTBOX");
                    if (data.length > 0) require(destAddr.isContract(), "NO_CODE_AT_DEST");
                    address currentOutbox = activeOutbox;
                    activeOutbox = msg.sender;
                    // We set and reset active outbox around external call so activeOutbox remains valid during call
                    (success, returnData) = destAddr.call{ value: amount }(data);
                    activeOutbox = currentOutbox;
                    emit BridgeCallTriggered(msg.sender, destAddr, amount, data);
                }
                function setInbox(address inbox, bool enabled) external override onlyOwner {
                    InOutInfo storage info = allowedInboxesMap[inbox];
                    bool alreadyEnabled = info.allowed;
                    emit InboxToggle(inbox, enabled);
                    if ((alreadyEnabled && enabled) || (!alreadyEnabled && !enabled)) {
                        return;
                    }
                    if (enabled) {
                        allowedInboxesMap[inbox] = InOutInfo(allowedInboxList.length, true);
                        allowedInboxList.push(inbox);
                    } else {
                        allowedInboxList[info.index] = allowedInboxList[allowedInboxList.length - 1];
                        allowedInboxesMap[allowedInboxList[info.index]].index = info.index;
                        allowedInboxList.pop();
                        delete allowedInboxesMap[inbox];
                    }
                }
                function setOutbox(address outbox, bool enabled) external override onlyOwner {
                    InOutInfo storage info = allowedOutboxesMap[outbox];
                    bool alreadyEnabled = info.allowed;
                    emit OutboxToggle(outbox, enabled);
                    if ((alreadyEnabled && enabled) || (!alreadyEnabled && !enabled)) {
                        return;
                    }
                    if (enabled) {
                        allowedOutboxesMap[outbox] = InOutInfo(allowedOutboxList.length, true);
                        allowedOutboxList.push(outbox);
                    } else {
                        allowedOutboxList[info.index] = allowedOutboxList[allowedOutboxList.length - 1];
                        allowedOutboxesMap[allowedOutboxList[info.index]].index = info.index;
                        allowedOutboxList.pop();
                        delete allowedOutboxesMap[outbox];
                    }
                }
                function messageCount() external view override returns (uint256) {
                    return inboxAccs.length;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./interfaces/IInbox.sol";
            import "./interfaces/IBridge.sol";
            import "../rollup/Rollup.sol";
            import "./Messages.sol";
            import "../libraries/Cloneable.sol";
            import "../libraries/Whitelist.sol";
            import "../libraries/ProxyUtil.sol";
            import "../libraries/AddressAliasHelper.sol";
            import "@openzeppelin/contracts/utils/Address.sol";
            import "./Bridge.sol";
            contract Inbox is IInbox, WhitelistConsumer, Cloneable {
                uint8 internal constant ETH_TRANSFER = 0;
                uint8 internal constant L2_MSG = 3;
                uint8 internal constant L1MessageType_L2FundedByL1 = 7;
                uint8 internal constant L1MessageType_submitRetryableTx = 9;
                uint8 internal constant L2MessageType_unsignedEOATx = 0;
                uint8 internal constant L2MessageType_unsignedContractTx = 1;
                IBridge public override bridge;
                bool public isEthDepositPaused;
                bool public shouldRewriteSender;
                function initialize(IBridge _bridge, address _whitelist) external {
                    require(address(bridge) == address(0), "ALREADY_INIT");
                    bridge = _bridge;
                    WhitelistConsumer.whitelist = _whitelist;
                }
                /**
                 * @notice Send a generic L2 message to the chain
                 * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input
                 * @param messageData Data of the message being sent
                 */
                function sendL2MessageFromOrigin(bytes calldata messageData)
                    external
                    onlyWhitelisted
                    returns (uint256)
                {
                    // solhint-disable-next-line avoid-tx-origin
                    require(msg.sender == tx.origin, "origin only");
                    uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(messageData));
                    emit InboxMessageDeliveredFromOrigin(msgNum);
                    return msgNum;
                }
                /**
                 * @notice Send a generic L2 message to the chain
                 * @dev This method can be used to send any type of message that doesn't require L1 validation
                 * @param messageData Data of the message being sent
                 */
                function sendL2Message(bytes calldata messageData)
                    external
                    override
                    onlyWhitelisted
                    returns (uint256)
                {
                    uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(messageData));
                    emit InboxMessageDelivered(msgNum, messageData);
                    return msgNum;
                }
                function sendL1FundedUnsignedTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    uint256 nonce,
                    address destAddr,
                    bytes calldata data
                ) external payable virtual override onlyWhitelisted returns (uint256) {
                    return
                        _deliverMessage(
                            L1MessageType_L2FundedByL1,
                            msg.sender,
                            abi.encodePacked(
                                L2MessageType_unsignedEOATx,
                                maxGas,
                                gasPriceBid,
                                nonce,
                                uint256(uint160(bytes20(destAddr))),
                                msg.value,
                                data
                            )
                        );
                }
                function sendL1FundedContractTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    address destAddr,
                    bytes calldata data
                ) external payable virtual override onlyWhitelisted returns (uint256) {
                    return
                        _deliverMessage(
                            L1MessageType_L2FundedByL1,
                            msg.sender,
                            abi.encodePacked(
                                L2MessageType_unsignedContractTx,
                                maxGas,
                                gasPriceBid,
                                uint256(uint160(bytes20(destAddr))),
                                msg.value,
                                data
                            )
                        );
                }
                function sendUnsignedTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    uint256 nonce,
                    address destAddr,
                    uint256 amount,
                    bytes calldata data
                ) external virtual override onlyWhitelisted returns (uint256) {
                    return
                        _deliverMessage(
                            L2_MSG,
                            msg.sender,
                            abi.encodePacked(
                                L2MessageType_unsignedEOATx,
                                maxGas,
                                gasPriceBid,
                                nonce,
                                uint256(uint160(bytes20(destAddr))),
                                amount,
                                data
                            )
                        );
                }
                function sendContractTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    address destAddr,
                    uint256 amount,
                    bytes calldata data
                ) external virtual override onlyWhitelisted returns (uint256) {
                    return
                        _deliverMessage(
                            L2_MSG,
                            msg.sender,
                            abi.encodePacked(
                                L2MessageType_unsignedContractTx,
                                maxGas,
                                gasPriceBid,
                                uint256(uint160(bytes20(destAddr))),
                                amount,
                                data
                            )
                        );
                }
                modifier onlyOwner() {
                    // the rollup contract owns the bridge
                    address rollup = Bridge(address(bridge)).owner();
                    // we want to validate the owner of the rollup
                    address owner = RollupBase(rollup).owner();
                    require(msg.sender == owner, "NOT_ROLLUP");
                    _;
                }
                event PauseToggled(bool enabled);
                /// @notice pauses eth deposits
                function pauseEthDeposits() external override onlyOwner {
                    require(!isEthDepositPaused, "ALREADY_PAUSED");
                    isEthDepositPaused = true;
                    emit PauseToggled(true);
                }
                /// @notice unpauses eth deposits
                function unpauseEthDeposits() external override onlyOwner {
                    require(isEthDepositPaused, "NOT_PAUSED");
                    isEthDepositPaused = false;
                    emit PauseToggled(false);
                }
                event RewriteToggled(bool enabled);
                /// @notice start rewriting addresses in eth deposits
                function startRewriteAddress() external override onlyOwner {
                    require(!shouldRewriteSender, "ALREADY_REWRITING");
                    shouldRewriteSender = true;
                    emit RewriteToggled(true);
                }
                /// @notice stop rewriting addresses in eth deposits
                function stopRewriteAddress() external override onlyOwner {
                    require(shouldRewriteSender, "NOT_REWRITING");
                    shouldRewriteSender = false;
                    emit RewriteToggled(false);
                }
                /// @notice deposit eth from L1 to L2
                /// @dev this function should not be called inside contract constructors
                function depositEth(uint256 maxSubmissionCost)
                    external
                    payable
                    virtual
                    override
                    onlyWhitelisted
                    returns (uint256)
                {
                    require(!isEthDepositPaused, "ETH_DEPOSIT_PAUSED");
                    address sender = msg.sender;
                    if (shouldRewriteSender && !Address.isContract(sender) && tx.origin == msg.sender) {
                        // isContract check fails if this function is called during a contract's constructor.
                        // We don't adjust the address for calls coming from L1 contracts since their addresses get remapped
                        // If the caller is an EOA, we adjust the address.
                        // This is needed because unsigned messages to the L2 (such as retryables)
                        // have the L1 sender address mapped.
                        // Here we preemptively reverse the mapping for EOAs so deposits work as expected
                        sender = AddressAliasHelper.undoL1ToL2Alias(sender);
                    }
                    return
                        _deliverMessage(
                            L1MessageType_submitRetryableTx,
                            sender,
                            abi.encodePacked(
                                // the beneficiary and other refund addresses don't get rewritten by arb-os
                                // so we use the original msg.sender value
                                uint256(uint160(bytes20(msg.sender))),
                                uint256(0),
                                msg.value,
                                maxSubmissionCost,
                                uint256(uint160(bytes20(msg.sender))),
                                uint256(uint160(bytes20(msg.sender))),
                                uint256(0),
                                uint256(0),
                                uint256(0),
                                ""
                            )
                        );
                }
                /**
                 * @notice Put an message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
                 * @dev all msg.value will deposited to callValueRefundAddress on L2
                 * @param destAddr destination L2 contract address
                 * @param l2CallValue call value for retryable L2 message
                 * @param  maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
                 * @param excessFeeRefundAddress maxgas x gasprice - execution cost gets credited here on L2 balance
                 * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
                 * @param maxGas Max gas deducted from user's L2 balance to cover L2 execution
                 * @param gasPriceBid price bid for L2 execution
                 * @param data ABI encoded data of L2 message
                 * @return unique id for retryable transaction (keccak256(requestID, uint(0) )
                 */
                function createRetryableTicket(
                    address destAddr,
                    uint256 l2CallValue,
                    uint256 maxSubmissionCost,
                    address excessFeeRefundAddress,
                    address callValueRefundAddress,
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    bytes calldata data
                ) external payable virtual override onlyWhitelisted returns (uint256) {
                    return
                        _deliverMessage(
                            L1MessageType_submitRetryableTx,
                            msg.sender,
                            abi.encodePacked(
                                uint256(uint160(bytes20(destAddr))),
                                l2CallValue,
                                msg.value,
                                maxSubmissionCost,
                                uint256(uint160(bytes20(excessFeeRefundAddress))),
                                uint256(uint160(bytes20(callValueRefundAddress))),
                                maxGas,
                                gasPriceBid,
                                data.length,
                                data
                            )
                        );
                }
                function _deliverMessage(
                    uint8 _kind,
                    address _sender,
                    bytes memory _messageData
                ) internal returns (uint256) {
                    uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));
                    emit InboxMessageDelivered(msgNum, _messageData);
                    return msgNum;
                }
                function deliverToBridge(
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                ) internal returns (uint256) {
                    return bridge.deliverMessageToInbox{ value: msg.value }(kind, sender, messageDataHash);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./interfaces/IOutbox.sol";
            import "./interfaces/IBridge.sol";
            import "./Messages.sol";
            import "../libraries/MerkleLib.sol";
            import "../libraries/BytesLib.sol";
            import "../libraries/Cloneable.sol";
            import "@openzeppelin/contracts/proxy/BeaconProxy.sol";
            import "@openzeppelin/contracts/proxy/UpgradeableBeacon.sol";
            contract Outbox is IOutbox, Cloneable {
                using BytesLib for bytes;
                struct OutboxEntry {
                    // merkle root of outputs
                    bytes32 root;
                    // mapping from output id => is spent
                    mapping(bytes32 => bool) spentOutput;
                }
                bytes1 internal constant MSG_ROOT = 0;
                uint8 internal constant SendType_sendTxToL1 = 3;
                address public rollup;
                IBridge public bridge;
                mapping(uint256 => OutboxEntry) public outboxEntries;
                struct L2ToL1Context {
                    uint128 l2Block;
                    uint128 l1Block;
                    uint128 timestamp;
                    uint128 batchNum;
                    bytes32 outputId;
                    address sender;
                }
                // Note, these variables are set and then wiped during a single transaction.
                // Therefore their values don't need to be maintained, and their slots will
                // be empty outside of transactions
                L2ToL1Context internal context;
                uint128 public constant OUTBOX_VERSION = 1;
                function initialize(address _rollup, IBridge _bridge) external {
                    require(rollup == address(0), "ALREADY_INIT");
                    rollup = _rollup;
                    bridge = _bridge;
                }
                /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
                /// When the return value is zero, that means this is a system message
                /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
                function l2ToL1Sender() external view override returns (address) {
                    return context.sender;
                }
                function l2ToL1Block() external view override returns (uint256) {
                    return uint256(context.l2Block);
                }
                function l2ToL1EthBlock() external view override returns (uint256) {
                    return uint256(context.l1Block);
                }
                function l2ToL1Timestamp() external view override returns (uint256) {
                    return uint256(context.timestamp);
                }
                function l2ToL1BatchNum() external view override returns (uint256) {
                    return uint256(context.batchNum);
                }
                function l2ToL1OutputId() external view override returns (bytes32) {
                    return context.outputId;
                }
                function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths)
                    external
                    override
                {
                    require(msg.sender == rollup, "ONLY_ROLLUP");
                    // If we've reached here, we've already confirmed that sum(sendLengths) == sendsData.length
                    uint256 messageCount = sendLengths.length;
                    uint256 offset = 0;
                    for (uint256 i = 0; i < messageCount; i++) {
                        handleOutgoingMessage(bytes(sendsData[offset:offset + sendLengths[i]]));
                        offset += sendLengths[i];
                    }
                }
                function handleOutgoingMessage(bytes memory data) private {
                    // Otherwise we have an unsupported message type and we skip the message
                    if (data[0] == MSG_ROOT) {
                        require(data.length == 97, "BAD_LENGTH");
                        uint256 batchNum = data.toUint(1);
                        // Ensure no outbox entry already exists w/ batch number
                        require(!outboxEntryExists(batchNum), "ENTRY_ALREADY_EXISTS");
                        // This is the total number of msgs included in the root, it can be used to
                        // detect when all msgs were executed against a root.
                        // It currently isn't stored, but instead emitted in an event for utility
                        uint256 numInBatch = data.toUint(33);
                        bytes32 outputRoot = data.toBytes32(65);
                        OutboxEntry memory newOutboxEntry = OutboxEntry(outputRoot);
                        outboxEntries[batchNum] = newOutboxEntry;
                        // keeping redundant batchnum in event (batchnum and old outboxindex field) for outbox version interface compatibility
                        emit OutboxEntryCreated(batchNum, batchNum, outputRoot, numInBatch);
                    }
                }
                /**
                 * @notice Executes a messages in an Outbox entry.
                 * @dev Reverts if dispute period hasn't expired, since the outbox entry
                 * is only created once the rollup confirms the respective assertion.
                 * @param batchNum Index of OutboxEntry in outboxEntries array
                 * @param proof Merkle proof of message inclusion in outbox entry
                 * @param index Merkle path to message
                 * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
                 * @param destAddr destination address for L1 contract call
                 * @param l2Block l2 block number at which sendTxToL1 call was made
                 * @param l1Block l1 block number at which sendTxToL1 call was made
                 * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
                 * @param amount value in L1 message in wei
                 * @param calldataForL1 abi-encoded L1 message data
                 */
                function executeTransaction(
                    uint256 batchNum,
                    bytes32[] calldata proof,
                    uint256 index,
                    address l2Sender,
                    address destAddr,
                    uint256 l2Block,
                    uint256 l1Block,
                    uint256 l2Timestamp,
                    uint256 amount,
                    bytes calldata calldataForL1
                ) external override {
                    bytes32 outputId;
                    {
                        bytes32 userTx =
                            calculateItemHash(
                                l2Sender,
                                destAddr,
                                l2Block,
                                l1Block,
                                l2Timestamp,
                                amount,
                                calldataForL1
                            );
                        outputId = recordOutputAsSpent(batchNum, proof, index, userTx);
                        emit OutBoxTransactionExecuted(destAddr, l2Sender, batchNum, index);
                    }
                    // we temporarily store the previous values so the outbox can naturally
                    // unwind itself when there are nested calls to `executeTransaction`
                    L2ToL1Context memory prevContext = context;
                    context = L2ToL1Context({
                        sender: l2Sender,
                        l2Block: uint128(l2Block),
                        l1Block: uint128(l1Block),
                        timestamp: uint128(l2Timestamp),
                        batchNum: uint128(batchNum),
                        outputId: outputId
                    });
                    // set and reset vars around execution so they remain valid during call
                    executeBridgeCall(destAddr, amount, calldataForL1);
                    context = prevContext;
                }
                function recordOutputAsSpent(
                    uint256 batchNum,
                    bytes32[] memory proof,
                    uint256 path,
                    bytes32 item
                ) internal returns (bytes32) {
                    require(proof.length < 256, "PROOF_TOO_LONG");
                    require(path < 2**proof.length, "PATH_NOT_MINIMAL");
                    // Hash the leaf an extra time to prove it's a leaf
                    bytes32 calcRoot = calculateMerkleRoot(proof, path, item);
                    OutboxEntry storage outboxEntry = outboxEntries[batchNum];
                    require(outboxEntry.root != bytes32(0), "NO_OUTBOX_ENTRY");
                    // With a minimal path, the pair of path and proof length should always identify
                    // a unique leaf. The path itself is not enough since the path length to different
                    // leaves could potentially be different
                    bytes32 uniqueKey = keccak256(abi.encodePacked(path, proof.length));
                    require(!outboxEntry.spentOutput[uniqueKey], "ALREADY_SPENT");
                    require(calcRoot == outboxEntry.root, "BAD_ROOT");
                    outboxEntry.spentOutput[uniqueKey] = true;
                    return uniqueKey;
                }
                function executeBridgeCall(
                    address destAddr,
                    uint256 amount,
                    bytes memory data
                ) internal {
                    (bool success, bytes memory returndata) = bridge.executeCall(destAddr, amount, data);
                    if (!success) {
                        if (returndata.length > 0) {
                            // solhint-disable-next-line no-inline-assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert("BRIDGE_CALL_FAILED");
                        }
                    }
                }
                function calculateItemHash(
                    address l2Sender,
                    address destAddr,
                    uint256 l2Block,
                    uint256 l1Block,
                    uint256 l2Timestamp,
                    uint256 amount,
                    bytes calldata calldataForL1
                ) public pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                SendType_sendTxToL1,
                                uint256(uint160(bytes20(l2Sender))),
                                uint256(uint160(bytes20(destAddr))),
                                l2Block,
                                l1Block,
                                l2Timestamp,
                                amount,
                                calldataForL1
                            )
                        );
                }
                function calculateMerkleRoot(
                    bytes32[] memory proof,
                    uint256 path,
                    bytes32 item
                ) public pure returns (bytes32) {
                    return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
                }
                function outboxEntryExists(uint256 batchNum) public view override returns (bool) {
                    return outboxEntries[batchNum].root != bytes32(0);
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "../utils/ContextUpgradeable.sol";
            import "../proxy/Initializable.sol";
            /**
             * @dev Contract module which provides a basic access control mechanism, where
             * there is an account (an owner) that can be granted exclusive access to
             * specific functions.
             *
             * By default, the owner account will be the one that deploys the contract. This
             * can later be changed with {transferOwnership}.
             *
             * This module is used through inheritance. It will make available the modifier
             * `onlyOwner`, which can be applied to your functions to restrict their use to
             * the owner.
             */
            abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
                address private _owner;
                event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                /**
                 * @dev Initializes the contract setting the deployer as the initial owner.
                 */
                function __Ownable_init() internal initializer {
                    __Context_init_unchained();
                    __Ownable_init_unchained();
                }
                function __Ownable_init_unchained() internal initializer {
                    address msgSender = _msgSender();
                    _owner = msgSender;
                    emit OwnershipTransferred(address(0), msgSender);
                }
                /**
                 * @dev Returns the address of the current owner.
                 */
                function owner() public view virtual returns (address) {
                    return _owner;
                }
                /**
                 * @dev Throws if called by any account other than the owner.
                 */
                modifier onlyOwner() {
                    require(owner() == _msgSender(), "Ownable: caller is not the owner");
                    _;
                }
                /**
                 * @dev Leaves the contract without owner. It will not be possible to call
                 * `onlyOwner` functions anymore. Can only be called by the current owner.
                 *
                 * NOTE: Renouncing ownership will leave the contract without an owner,
                 * thereby removing any functionality that is only available to the owner.
                 */
                function renounceOwnership() public virtual onlyOwner {
                    emit OwnershipTransferred(_owner, address(0));
                    _owner = address(0);
                }
                /**
                 * @dev Transfers ownership of the contract to a new account (`newOwner`).
                 * Can only be called by the current owner.
                 */
                function transferOwnership(address newOwner) public virtual onlyOwner {
                    require(newOwner != address(0), "Ownable: new owner is the zero address");
                    emit OwnershipTransferred(_owner, newOwner);
                    _owner = newOwner;
                }
                uint256[49] private __gap;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.2 <0.8.0;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize, which returns 0 for contracts in
                    // construction, since the code is only stored at the end of the
                    // constructor execution.
                    uint256 size;
                    // solhint-disable-next-line no-inline-assembly
                    assembly { size := extcodesize(account) }
                    return size > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                    (bool success, ) = recipient.call{ value: amount }("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain`call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                  return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.call{ value: value }(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    require(isContract(target), "Address: delegate call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            // solhint-disable-next-line no-inline-assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface IBridge {
                event MessageDelivered(
                    uint256 indexed messageIndex,
                    bytes32 indexed beforeInboxAcc,
                    address inbox,
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                );
                event BridgeCallTriggered(
                    address indexed outbox,
                    address indexed destAddr,
                    uint256 amount,
                    bytes data
                );
                event InboxToggle(address indexed inbox, bool enabled);
                event OutboxToggle(address indexed outbox, bool enabled);
                function deliverMessageToInbox(
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                ) external payable returns (uint256);
                function executeCall(
                    address destAddr,
                    uint256 amount,
                    bytes calldata data
                ) external returns (bool success, bytes memory returnData);
                // These are only callable by the admin
                function setInbox(address inbox, bool enabled) external;
                function setOutbox(address inbox, bool enabled) external;
                // View functions
                function activeOutbox() external view returns (address);
                function allowedInboxes(address inbox) external view returns (bool);
                function allowedOutboxes(address outbox) external view returns (bool);
                function inboxAccs(uint256 index) external view returns (bytes32);
                function messageCount() external view returns (uint256);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./IBridge.sol";
            import "./IMessageProvider.sol";
            interface IInbox is IMessageProvider {
                function sendL2Message(bytes calldata messageData) external returns (uint256);
                function sendUnsignedTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    uint256 nonce,
                    address destAddr,
                    uint256 amount,
                    bytes calldata data
                ) external returns (uint256);
                function sendContractTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    address destAddr,
                    uint256 amount,
                    bytes calldata data
                ) external returns (uint256);
                function sendL1FundedUnsignedTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    uint256 nonce,
                    address destAddr,
                    bytes calldata data
                ) external payable returns (uint256);
                function sendL1FundedContractTransaction(
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    address destAddr,
                    bytes calldata data
                ) external payable returns (uint256);
                function createRetryableTicket(
                    address destAddr,
                    uint256 arbTxCallValue,
                    uint256 maxSubmissionCost,
                    address submissionRefundAddress,
                    address valueRefundAddress,
                    uint256 maxGas,
                    uint256 gasPriceBid,
                    bytes calldata data
                ) external payable returns (uint256);
                function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);
                function bridge() external view returns (IBridge);
                function pauseEthDeposits() external;
                function unpauseEthDeposits() external;
                function startRewriteAddress() external;
                function stopRewriteAddress() external;
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "@openzeppelin/contracts/utils/Pausable.sol";
            import "@openzeppelin/contracts/proxy/Proxy.sol";
            import "@openzeppelin/contracts/utils/Address.sol";
            import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
            import "./RollupEventBridge.sol";
            import "./RollupCore.sol";
            import "./RollupLib.sol";
            import "./INode.sol";
            import "./INodeFactory.sol";
            import "../challenge/IChallenge.sol";
            import "../challenge/IChallengeFactory.sol";
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/IOutbox.sol";
            import "../bridge/Messages.sol";
            import "../libraries/ProxyUtil.sol";
            import "../libraries/Cloneable.sol";
            import "./facets/IRollupFacets.sol";
            abstract contract RollupBase is Cloneable, RollupCore, Pausable {
                // Rollup Config
                uint256 public confirmPeriodBlocks;
                uint256 public extraChallengeTimeBlocks;
                uint256 public avmGasSpeedLimitPerBlock;
                uint256 public baseStake;
                // Bridge is an IInbox and IOutbox
                IBridge public delayedBridge;
                ISequencerInbox public sequencerBridge;
                IOutbox public outbox;
                RollupEventBridge public rollupEventBridge;
                IChallengeFactory public challengeFactory;
                INodeFactory public nodeFactory;
                address public owner;
                address public stakeToken;
                uint256 public minimumAssertionPeriod;
                uint256 public STORAGE_GAP_1;
                uint256 public STORAGE_GAP_2;
                uint256 public challengeExecutionBisectionDegree;
                address[] internal facets;
                mapping(address => bool) isValidator;
                /// @notice DEPRECATED -- this method is deprecated but still mantained for backward compatibility
                /// @dev this actually returns the avmGasSpeedLimitPerBlock
                /// @return this actually returns the avmGasSpeedLimitPerBlock
                function arbGasSpeedLimitPerBlock() external view returns (uint256) {
                    return avmGasSpeedLimitPerBlock;
                }
            }
            contract Rollup is Proxy, RollupBase {
                using Address for address;
                constructor(uint256 _confirmPeriodBlocks) public Cloneable() Pausable() {
                    // constructor is used so logic contract can't be init'ed
                    confirmPeriodBlocks = _confirmPeriodBlocks;
                    require(isInit(), "CONSTRUCTOR_NOT_INIT");
                }
                function isInit() internal view returns (bool) {
                    return confirmPeriodBlocks != 0;
                }
                // _rollupParams = [ confirmPeriodBlocks, extraChallengeTimeBlocks, avmGasSpeedLimitPerBlock, baseStake ]
                // connectedContracts = [delayedBridge, sequencerInbox, outbox, rollupEventBridge, challengeFactory, nodeFactory]
                function initialize(
                    bytes32 _machineHash,
                    uint256[4] calldata _rollupParams,
                    address _stakeToken,
                    address _owner,
                    bytes calldata _extraConfig,
                    address[6] calldata connectedContracts,
                    address[2] calldata _facets,
                    uint256[2] calldata sequencerInboxParams
                ) public {
                    require(!isInit(), "ALREADY_INIT");
                    // calls initialize method in user facet
                    require(_facets[0].isContract(), "FACET_0_NOT_CONTRACT");
                    require(_facets[1].isContract(), "FACET_1_NOT_CONTRACT");
                    (bool success, ) = _facets[1].delegatecall(
                        abi.encodeWithSelector(IRollupUser.initialize.selector, _stakeToken)
                    );
                    require(success, "FAIL_INIT_FACET");
                    delayedBridge = IBridge(connectedContracts[0]);
                    sequencerBridge = ISequencerInbox(connectedContracts[1]);
                    outbox = IOutbox(connectedContracts[2]);
                    delayedBridge.setOutbox(connectedContracts[2], true);
                    rollupEventBridge = RollupEventBridge(connectedContracts[3]);
                    delayedBridge.setInbox(connectedContracts[3], true);
                    rollupEventBridge.rollupInitialized(
                        _rollupParams[0],
                        _rollupParams[2],
                        _owner,
                        _extraConfig
                    );
                    challengeFactory = IChallengeFactory(connectedContracts[4]);
                    nodeFactory = INodeFactory(connectedContracts[5]);
                    INode node = createInitialNode(_machineHash);
                    initializeCore(node);
                    confirmPeriodBlocks = _rollupParams[0];
                    extraChallengeTimeBlocks = _rollupParams[1];
                    avmGasSpeedLimitPerBlock = _rollupParams[2];
                    baseStake = _rollupParams[3];
                    owner = _owner;
                    // A little over 15 minutes
                    minimumAssertionPeriod = 75;
                    challengeExecutionBisectionDegree = 400;
                    sequencerBridge.setMaxDelay(sequencerInboxParams[0], sequencerInboxParams[1]);
                    // facets[0] == admin, facets[1] == user
                    facets = _facets;
                    emit RollupCreated(_machineHash);
                    require(isInit(), "INITIALIZE_NOT_INIT");
                }
                function postUpgradeInit() external {
                    // it is assumed the rollup contract is behind a Proxy controlled by a proxy admin
                    // this function can only be called by the proxy admin contract
                    address proxyAdmin = ProxyUtil.getProxyAdmin();
                    require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
                    // this upgrade moves the delay blocks and seconds tracking to the sequencer inbox
                    // because of that we need to update the admin facet logic to allow the owner to set
                    // these values in the sequencer inbox
                    STORAGE_GAP_1 = 0;
                    STORAGE_GAP_2 = 0;
                }
                function createInitialNode(bytes32 _machineHash) private returns (INode) {
                    bytes32 state = RollupLib.stateHash(
                        RollupLib.ExecutionState(
                            0, // total gas used
                            _machineHash,
                            0, // inbox count
                            0, // send count
                            0, // log count
                            0, // send acc
                            0, // log acc
                            block.number, // block proposed
                            1 // Initialization message already in inbox
                        )
                    );
                    return
                        INode(
                            nodeFactory.createNode(
                                state,
                                0, // challenge hash (not challengeable)
                                0, // confirm data
                                0, // prev node
                                block.number // deadline block (not challengeable)
                            )
                        );
                }
                /**
                 * This contract uses a dispatch pattern from EIP-2535: Diamonds
                 * together with Open Zeppelin's proxy
                 */
                function getFacets() external view returns (address, address) {
                    return (getAdminFacet(), getUserFacet());
                }
                function getAdminFacet() public view returns (address) {
                    return facets[0];
                }
                function getUserFacet() public view returns (address) {
                    return facets[1];
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual override returns (address) {
                    require(msg.data.length >= 4, "NO_FUNC_SIG");
                    address rollupOwner = owner;
                    // if there is an owner and it is the sender, delegate to admin facet
                    address target = rollupOwner != address(0) && rollupOwner == msg.sender
                        ? getAdminFacet()
                        : getUserFacet();
                    require(target.isContract(), "TARGET_NOT_CONTRACT");
                    return target;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library Messages {
                function messageHash(
                    uint8 kind,
                    address sender,
                    uint256 blockNumber,
                    uint256 timestamp,
                    uint256 inboxSeqNum,
                    uint256 gasPriceL1,
                    bytes32 messageDataHash
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                kind,
                                sender,
                                blockNumber,
                                timestamp,
                                inboxSeqNum,
                                gasPriceL1,
                                messageDataHash
                            )
                        );
                }
                function addMessageToInbox(bytes32 inbox, bytes32 message) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(inbox, message));
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2020, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./ICloneable.sol";
            contract Cloneable is ICloneable {
                string private constant NOT_CLONE = "NOT_CLONE";
                bool private isMasterCopy;
                constructor() public {
                    isMasterCopy = true;
                }
                function isMaster() external view override returns (bool) {
                    return isMasterCopy;
                }
                function safeSelfDestruct(address payable dest) internal {
                    require(!isMasterCopy, NOT_CLONE);
                    selfdestruct(dest);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            abstract contract WhitelistConsumer {
                address public whitelist;
                event WhitelistSourceUpdated(address newSource);
                modifier onlyWhitelisted {
                    if (whitelist != address(0)) {
                        require(Whitelist(whitelist).isAllowed(msg.sender), "NOT_WHITELISTED");
                    }
                    _;
                }
                function updateWhitelistSource(address newSource) external {
                    require(msg.sender == whitelist, "NOT_FROM_LIST");
                    whitelist = newSource;
                    emit WhitelistSourceUpdated(newSource);
                }
            }
            contract Whitelist {
                address public owner;
                mapping(address => bool) public isAllowed;
                event OwnerUpdated(address newOwner);
                event WhitelistUpgraded(address newWhitelist, address[] targets);
                constructor() public {
                    owner = msg.sender;
                }
                modifier onlyOwner {
                    require(msg.sender == owner, "ONLY_OWNER");
                    _;
                }
                function setOwner(address newOwner) external onlyOwner {
                    owner = newOwner;
                    emit OwnerUpdated(newOwner);
                }
                function setWhitelist(address[] memory user, bool[] memory val) external onlyOwner {
                    require(user.length == val.length, "INVALID_INPUT");
                    for (uint256 i = 0; i < user.length; i++) {
                        isAllowed[user[i]] = val[i];
                    }
                }
                // set new whitelist to address(0) to disable whitelist
                function triggerConsumers(address newWhitelist, address[] memory targets) external onlyOwner {
                    for (uint256 i = 0; i < targets.length; i++) {
                        WhitelistConsumer(targets[i]).updateWhitelistSource(newWhitelist);
                    }
                    emit WhitelistUpgraded(newWhitelist, targets);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library ProxyUtil {
                function getProxyAdmin() internal view returns (address admin) {
                    // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/proxy/TransparentUpgradeableProxy.sol#L48
                    // Storage slot with the admin of the proxy contract.
                    // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                    bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                    assembly {
                        admin := sload(slot)
                    }
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library AddressAliasHelper {
                /// @notice Utility function that converts the msg.sender viewed in the L2 to the
                /// address in the L1 that submitted a tx to the inbox
                /// @param l2address L2 address as viewed in msg.sender
                /// @return l1Address the address in the L1 that triggered the tx to L2
                function undoL1ToL2Alias(address l2address) internal pure returns (address l1Address) {
                    uint160 offset = uint160(0x1111000000000000000000000000000000001111);
                    l1Address = address(uint160(l2address) - offset);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface IMessageProvider {
                event InboxMessageDelivered(uint256 indexed messageNum, bytes data);
                event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./Context.sol";
            /**
             * @dev Contract module which allows children to implement an emergency stop
             * mechanism that can be triggered by an authorized account.
             *
             * This module is used through inheritance. It will make available the
             * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
             * the functions of your contract. Note that they will not be pausable by
             * simply including this module, only once the modifiers are put in place.
             */
            abstract contract Pausable is Context {
                /**
                 * @dev Emitted when the pause is triggered by `account`.
                 */
                event Paused(address account);
                /**
                 * @dev Emitted when the pause is lifted by `account`.
                 */
                event Unpaused(address account);
                bool private _paused;
                /**
                 * @dev Initializes the contract in unpaused state.
                 */
                constructor () internal {
                    _paused = false;
                }
                /**
                 * @dev Returns true if the contract is paused, and false otherwise.
                 */
                function paused() public view virtual returns (bool) {
                    return _paused;
                }
                /**
                 * @dev Modifier to make a function callable only when the contract is not paused.
                 *
                 * Requirements:
                 *
                 * - The contract must not be paused.
                 */
                modifier whenNotPaused() {
                    require(!paused(), "Pausable: paused");
                    _;
                }
                /**
                 * @dev Modifier to make a function callable only when the contract is paused.
                 *
                 * Requirements:
                 *
                 * - The contract must be paused.
                 */
                modifier whenPaused() {
                    require(paused(), "Pausable: not paused");
                    _;
                }
                /**
                 * @dev Triggers stopped state.
                 *
                 * Requirements:
                 *
                 * - The contract must not be paused.
                 */
                function _pause() internal virtual whenNotPaused {
                    _paused = true;
                    emit Paused(_msgSender());
                }
                /**
                 * @dev Returns to normal state.
                 *
                 * Requirements:
                 *
                 * - The contract must be paused.
                 */
                function _unpause() internal virtual whenPaused {
                    _paused = false;
                    emit Unpaused(_msgSender());
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 { revert(0, returndatasize()) }
                        default { return(0, returndatasize()) }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive () external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overriden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev Interface of the ERC20 standard as defined in the EIP.
             */
            interface IERC20 {
                /**
                 * @dev Returns the amount of tokens in existence.
                 */
                function totalSupply() external view returns (uint256);
                /**
                 * @dev Returns the amount of tokens owned by `account`.
                 */
                function balanceOf(address account) external view returns (uint256);
                /**
                 * @dev Moves `amount` tokens from the caller's account to `recipient`.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transfer(address recipient, uint256 amount) external returns (bool);
                /**
                 * @dev Returns the remaining number of tokens that `spender` will be
                 * allowed to spend on behalf of `owner` through {transferFrom}. This is
                 * zero by default.
                 *
                 * This value changes when {approve} or {transferFrom} are called.
                 */
                function allowance(address owner, address spender) external view returns (uint256);
                /**
                 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * IMPORTANT: Beware that changing an allowance with this method brings the risk
                 * that someone may use both the old and the new allowance by unfortunate
                 * transaction ordering. One possible solution to mitigate this race
                 * condition is to first reduce the spender's allowance to 0 and set the
                 * desired value afterwards:
                 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                 *
                 * Emits an {Approval} event.
                 */
                function approve(address spender, uint256 amount) external returns (bool);
                /**
                 * @dev Moves `amount` tokens from `sender` to `recipient` using the
                 * allowance mechanism. `amount` is then deducted from the caller's
                 * allowance.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
                /**
                 * @dev Emitted when `value` tokens are moved from one account (`from`) to
                 * another (`to`).
                 *
                 * Note that `value` may be zero.
                 */
                event Transfer(address indexed from, address indexed to, uint256 value);
                /**
                 * @dev Emitted when the allowance of a `spender` for an `owner` is set by
                 * a call to {approve}. `value` is the new allowance.
                 */
                event Approval(address indexed owner, address indexed spender, uint256 value);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./Rollup.sol";
            import "./facets/IRollupFacets.sol";
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/IMessageProvider.sol";
            import "./INode.sol";
            import "../libraries/Cloneable.sol";
            contract RollupEventBridge is IMessageProvider, Cloneable {
                uint8 internal constant INITIALIZATION_MSG_TYPE = 11;
                uint8 internal constant ROLLUP_PROTOCOL_EVENT_TYPE = 8;
                uint8 internal constant CREATE_NODE_EVENT = 0;
                uint8 internal constant CONFIRM_NODE_EVENT = 1;
                uint8 internal constant REJECT_NODE_EVENT = 2;
                uint8 internal constant STAKE_CREATED_EVENT = 3;
                IBridge bridge;
                address rollup;
                modifier onlyRollup() {
                    require(msg.sender == rollup, "ONLY_ROLLUP");
                    _;
                }
                function initialize(address _bridge, address _rollup) external {
                    require(rollup == address(0), "ALREADY_INIT");
                    bridge = IBridge(_bridge);
                    rollup = _rollup;
                }
                function rollupInitialized(
                    uint256 confirmPeriodBlocks,
                    uint256 avmGasSpeedLimitPerBlock,
                    address owner,
                    bytes calldata extraConfig
                ) external onlyRollup {
                    bytes memory initMsg = abi.encodePacked(
                        keccak256("ChallengePeriodEthBlocks"),
                        confirmPeriodBlocks,
                        keccak256("SpeedLimitPerSecond"),
                        avmGasSpeedLimitPerBlock / 100, // convert avm gas to arbgas
                        keccak256("ChainOwner"),
                        uint256(uint160(bytes20(owner))),
                        extraConfig
                    );
                    uint256 num = bridge.deliverMessageToInbox(
                        INITIALIZATION_MSG_TYPE,
                        address(0),
                        keccak256(initMsg)
                    );
                    emit InboxMessageDelivered(num, initMsg);
                }
                function nodeCreated(
                    uint256 nodeNum,
                    uint256 prev,
                    uint256 deadline,
                    address asserter
                ) external onlyRollup {
                    deliverToBridge(
                        abi.encodePacked(
                            CREATE_NODE_EVENT,
                            nodeNum,
                            prev,
                            block.number,
                            deadline,
                            uint256(uint160(bytes20(asserter)))
                        )
                    );
                }
                function nodeConfirmed(uint256 nodeNum) external onlyRollup {
                    deliverToBridge(abi.encodePacked(CONFIRM_NODE_EVENT, nodeNum));
                }
                function nodeRejected(uint256 nodeNum) external onlyRollup {
                    deliverToBridge(abi.encodePacked(REJECT_NODE_EVENT, nodeNum));
                }
                function stakeCreated(address staker, uint256 nodeNum) external onlyRollup {
                    deliverToBridge(
                        abi.encodePacked(
                            STAKE_CREATED_EVENT,
                            uint256(uint160(bytes20(staker))),
                            nodeNum,
                            block.number
                        )
                    );
                }
                function deliverToBridge(bytes memory message) private {
                    emit InboxMessageDelivered(
                        bridge.deliverMessageToInbox(
                            ROLLUP_PROTOCOL_EVENT_TYPE,
                            msg.sender,
                            keccak256(message)
                        ),
                        message
                    );
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./INode.sol";
            import "./IRollupCore.sol";
            import "./RollupLib.sol";
            import "./INodeFactory.sol";
            import "./RollupEventBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            import "@openzeppelin/contracts/math/SafeMath.sol";
            contract RollupCore is IRollupCore {
                using SafeMath for uint256;
                // Stakers become Zombies after losing a challenge
                struct Zombie {
                    address stakerAddress;
                    uint256 latestStakedNode;
                }
                struct Staker {
                    uint256 index;
                    uint256 latestStakedNode;
                    uint256 amountStaked;
                    // currentChallenge is 0 if staker is not in a challenge
                    address currentChallenge;
                    bool isStaked;
                }
                uint256 private _latestConfirmed;
                uint256 private _firstUnresolvedNode;
                uint256 private _latestNodeCreated;
                uint256 private _lastStakeBlock;
                mapping(uint256 => INode) private _nodes;
                mapping(uint256 => bytes32) private _nodeHashes;
                address payable[] private _stakerList;
                mapping(address => Staker) public override _stakerMap;
                Zombie[] private _zombies;
                mapping(address => uint256) private _withdrawableFunds;
                /**
                 * @notice Get the address of the Node contract for the given node
                 * @param nodeNum Index of the node
                 * @return Address of the Node contract
                 */
                function getNode(uint256 nodeNum) public view override returns (INode) {
                    return _nodes[nodeNum];
                }
                /**
                 * @notice Get the address of the staker at the given index
                 * @param stakerNum Index of the staker
                 * @return Address of the staker
                 */
                function getStakerAddress(uint256 stakerNum) external view override returns (address) {
                    return _stakerList[stakerNum];
                }
                /**
                 * @notice Check whether the given staker is staked
                 * @param staker Staker address to check
                 * @return True or False for whether the staker was staked
                 */
                function isStaked(address staker) public view override returns (bool) {
                    return _stakerMap[staker].isStaked;
                }
                /**
                 * @notice Get the latest staked node of the given staker
                 * @param staker Staker address to lookup
                 * @return Latest node staked of the staker
                 */
                function latestStakedNode(address staker) public view override returns (uint256) {
                    return _stakerMap[staker].latestStakedNode;
                }
                /**
                 * @notice Get the current challenge of the given staker
                 * @param staker Staker address to lookup
                 * @return Current challenge of the staker
                 */
                function currentChallenge(address staker) public view override returns (address) {
                    return _stakerMap[staker].currentChallenge;
                }
                /**
                 * @notice Get the amount staked of the given staker
                 * @param staker Staker address to lookup
                 * @return Amount staked of the staker
                 */
                function amountStaked(address staker) public view override returns (uint256) {
                    return _stakerMap[staker].amountStaked;
                }
                /**
                 * @notice Get the original staker address of the zombie at the given index
                 * @param zombieNum Index of the zombie to lookup
                 * @return Original staker address of the zombie
                 */
                function zombieAddress(uint256 zombieNum) public view override returns (address) {
                    return _zombies[zombieNum].stakerAddress;
                }
                /**
                 * @notice Get Latest node that the given zombie at the given index is staked on
                 * @param zombieNum Index of the zombie to lookup
                 * @return Latest node that the given zombie is staked on
                 */
                function zombieLatestStakedNode(uint256 zombieNum) public view override returns (uint256) {
                    return _zombies[zombieNum].latestStakedNode;
                }
                /// @return Current number of un-removed zombies
                function zombieCount() public view override returns (uint256) {
                    return _zombies.length;
                }
                function isZombie(address staker) public view override returns (bool) {
                    for (uint256 i = 0; i < _zombies.length; i++) {
                        if (staker == _zombies[i].stakerAddress) {
                            return true;
                        }
                    }
                    return false;
                }
                /**
                 * @notice Get the amount of funds withdrawable by the given address
                 * @param owner Address to check the funds of
                 * @return Amount of funds withdrawable by owner
                 */
                function withdrawableFunds(address owner) external view override returns (uint256) {
                    return _withdrawableFunds[owner];
                }
                /**
                 * @return Index of the first unresolved node
                 * @dev If all nodes have been resolved, this will be latestNodeCreated + 1
                 */
                function firstUnresolvedNode() public view override returns (uint256) {
                    return _firstUnresolvedNode;
                }
                /// @return Index of the latest confirmed node
                function latestConfirmed() public view override returns (uint256) {
                    return _latestConfirmed;
                }
                /// @return Index of the latest rollup node created
                function latestNodeCreated() public view override returns (uint256) {
                    return _latestNodeCreated;
                }
                /// @return Ethereum block that the most recent stake was created
                function lastStakeBlock() external view override returns (uint256) {
                    return _lastStakeBlock;
                }
                /// @return Number of active stakers currently staked
                function stakerCount() public view override returns (uint256) {
                    return _stakerList.length;
                }
                /**
                 * @notice Initialize the core with an initial node
                 * @param initialNode Initial node to start the chain with
                 */
                function initializeCore(INode initialNode) internal {
                    _nodes[0] = initialNode;
                    _firstUnresolvedNode = 1;
                }
                /**
                 * @notice React to a new node being created by storing it an incrementing the latest node counter
                 * @param node Node that was newly created
                 * @param nodeHash The hash of said node
                 */
                function nodeCreated(INode node, bytes32 nodeHash) internal {
                    _latestNodeCreated++;
                    _nodes[_latestNodeCreated] = node;
                    _nodeHashes[_latestNodeCreated] = nodeHash;
                }
                /// @return Node hash as of this node number
                function getNodeHash(uint256 index) public view override returns (bytes32) {
                    return _nodeHashes[index];
                }
                /// @notice Reject the next unresolved node
                function _rejectNextNode() internal {
                    destroyNode(_firstUnresolvedNode);
                    _firstUnresolvedNode++;
                }
                /// @notice Confirm the next unresolved node
                function confirmNextNode(
                    bytes32 beforeSendAcc,
                    bytes calldata sendsData,
                    uint256[] calldata sendLengths,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount,
                    IOutbox outbox,
                    RollupEventBridge rollupEventBridge
                ) internal {
                    confirmNode(
                        _firstUnresolvedNode,
                        beforeSendAcc,
                        sendsData,
                        sendLengths,
                        afterSendCount,
                        afterLogAcc,
                        afterLogCount,
                        outbox,
                        rollupEventBridge
                    );
                }
                function confirmNode(
                    uint256 nodeNum,
                    bytes32 beforeSendAcc,
                    bytes calldata sendsData,
                    uint256[] calldata sendLengths,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount,
                    IOutbox outbox,
                    RollupEventBridge rollupEventBridge
                ) internal {
                    bytes32 afterSendAcc = RollupLib.feedAccumulator(sendsData, sendLengths, beforeSendAcc);
                    INode node = getNode(nodeNum);
                    // Authenticate data against node's confirm data pre-image
                    require(
                        node.confirmData() ==
                            RollupLib.confirmHash(
                                beforeSendAcc,
                                afterSendAcc,
                                afterLogAcc,
                                afterSendCount,
                                afterLogCount
                            ),
                        "CONFIRM_DATA"
                    );
                    // trusted external call to outbox
                    outbox.processOutgoingMessages(sendsData, sendLengths);
                    destroyNode(_latestConfirmed);
                    _latestConfirmed = nodeNum;
                    _firstUnresolvedNode = nodeNum + 1;
                    rollupEventBridge.nodeConfirmed(nodeNum);
                    emit NodeConfirmed(nodeNum, afterSendAcc, afterSendCount, afterLogAcc, afterLogCount);
                }
                /**
                 * @notice Create a new stake at latest confirmed node
                 * @param stakerAddress Address of the new staker
                 * @param depositAmount Stake amount of the new staker
                 */
                function createNewStake(address payable stakerAddress, uint256 depositAmount) internal {
                    uint256 stakerIndex = _stakerList.length;
                    _stakerList.push(stakerAddress);
                    _stakerMap[stakerAddress] = Staker(
                        stakerIndex,
                        _latestConfirmed,
                        depositAmount,
                        address(0), // new staker is not in challenge
                        true
                    );
                    _lastStakeBlock = block.number;
                    emit UserStakeUpdated(stakerAddress, 0, depositAmount);
                }
                /**
                 * @notice Check to see whether the two stakers are in the same challenge
                 * @param stakerAddress1 Address of the first staker
                 * @param stakerAddress2 Address of the second staker
                 * @return Address of the challenge that the two stakers are in
                 */
                function inChallenge(address stakerAddress1, address stakerAddress2)
                    internal
                    view
                    returns (address)
                {
                    Staker storage staker1 = _stakerMap[stakerAddress1];
                    Staker storage staker2 = _stakerMap[stakerAddress2];
                    address challenge = staker1.currentChallenge;
                    require(challenge != address(0), "NO_CHAL");
                    require(challenge == staker2.currentChallenge, "DIFF_IN_CHAL");
                    return challenge;
                }
                /**
                 * @notice Make the given staker as not being in a challenge
                 * @param stakerAddress Address of the staker to remove from a challenge
                 */
                function clearChallenge(address stakerAddress) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    staker.currentChallenge = address(0);
                }
                /**
                 * @notice Mark both the given stakers as engaged in the challenge
                 * @param staker1 Address of the first staker
                 * @param staker2 Address of the second staker
                 * @param challenge Address of the challenge both stakers are now in
                 */
                function challengeStarted(
                    address staker1,
                    address staker2,
                    address challenge
                ) internal {
                    _stakerMap[staker1].currentChallenge = challenge;
                    _stakerMap[staker2].currentChallenge = challenge;
                }
                /**
                 * @notice Add to the stake of the given staker by the given amount
                 * @param stakerAddress Address of the staker to increase the stake of
                 * @param amountAdded Amount of stake to add to the staker
                 */
                function increaseStakeBy(address stakerAddress, uint256 amountAdded) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 initialStaked = staker.amountStaked;
                    uint256 finalStaked = initialStaked.add(amountAdded);
                    staker.amountStaked = finalStaked;
                    emit UserStakeUpdated(stakerAddress, initialStaked, finalStaked);
                }
                /**
                 * @notice Reduce the stake of the given staker to the given target
                 * @param stakerAddress Address of the staker to reduce the stake of
                 * @param target Amount of stake to leave with the staker
                 * @return Amount of value released from the stake
                 */
                function reduceStakeTo(address stakerAddress, uint256 target) internal returns (uint256) {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 current = staker.amountStaked;
                    require(target <= current, "TOO_LITTLE_STAKE");
                    uint256 amountWithdrawn = current.sub(target);
                    staker.amountStaked = target;
                    increaseWithdrawableFunds(stakerAddress, amountWithdrawn);
                    emit UserStakeUpdated(stakerAddress, current, target);
                    return amountWithdrawn;
                }
                /**
                 * @notice Remove the given staker and turn them into a zombie
                 * @param stakerAddress Address of the staker to remove
                 */
                function turnIntoZombie(address stakerAddress) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    _zombies.push(Zombie(stakerAddress, staker.latestStakedNode));
                    deleteStaker(stakerAddress);
                }
                /**
                 * @notice Update the latest staked node of the zombie at the given index
                 * @param zombieNum Index of the zombie to move
                 * @param latest New latest node the zombie is staked on
                 */
                function zombieUpdateLatestStakedNode(uint256 zombieNum, uint256 latest) internal {
                    _zombies[zombieNum].latestStakedNode = latest;
                }
                /**
                 * @notice Remove the zombie at the given index
                 * @param zombieNum Index of the zombie to remove
                 */
                function removeZombie(uint256 zombieNum) internal {
                    _zombies[zombieNum] = _zombies[_zombies.length - 1];
                    _zombies.pop();
                }
                /**
                 * @notice Remove the given staker and return their stake
                 * @param stakerAddress Address of the staker withdrawing their stake
                 */
                function withdrawStaker(address stakerAddress) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 initialStaked = staker.amountStaked;
                    increaseWithdrawableFunds(stakerAddress, initialStaked);
                    deleteStaker(stakerAddress);
                    emit UserStakeUpdated(stakerAddress, initialStaked, 0);
                }
                /**
                 * @notice Advance the given staker to the given node
                 * @param stakerAddress Address of the staker adding their stake
                 * @param nodeNum Index of the node to stake on
                 */
                function stakeOnNode(
                    address stakerAddress,
                    uint256 nodeNum,
                    uint256 confirmPeriodBlocks
                ) internal {
                    Staker storage staker = _stakerMap[stakerAddress];
                    INode node = _nodes[nodeNum];
                    uint256 newStakerCount = node.addStaker(stakerAddress);
                    staker.latestStakedNode = nodeNum;
                    if (newStakerCount == 1) {
                        INode parent = _nodes[node.prev()];
                        parent.newChildConfirmDeadline(block.number.add(confirmPeriodBlocks));
                    }
                }
                /**
                 * @notice Clear the withdrawable funds for the given address
                 * @param owner Address of the account to remove funds from
                 * @return Amount of funds removed from account
                 */
                function withdrawFunds(address owner) internal returns (uint256) {
                    uint256 amount = _withdrawableFunds[owner];
                    _withdrawableFunds[owner] = 0;
                    emit UserWithdrawableFundsUpdated(owner, amount, 0);
                    return amount;
                }
                /**
                 * @notice Increase the withdrawable funds for the given address
                 * @param owner Address of the account to add withdrawable funds to
                 */
                function increaseWithdrawableFunds(address owner, uint256 amount) internal {
                    uint256 initialWithdrawable = _withdrawableFunds[owner];
                    uint256 finalWithdrawable = initialWithdrawable.add(amount);
                    _withdrawableFunds[owner] = finalWithdrawable;
                    emit UserWithdrawableFundsUpdated(owner, initialWithdrawable, finalWithdrawable);
                }
                /**
                 * @notice Remove the given staker
                 * @param stakerAddress Address of the staker to remove
                 */
                function deleteStaker(address stakerAddress) private {
                    Staker storage staker = _stakerMap[stakerAddress];
                    uint256 stakerIndex = staker.index;
                    _stakerList[stakerIndex] = _stakerList[_stakerList.length - 1];
                    _stakerMap[_stakerList[stakerIndex]].index = stakerIndex;
                    _stakerList.pop();
                    delete _stakerMap[stakerAddress];
                }
                /**
                 * @notice Destroy the given node and clear out its address
                 * @param nodeNum Index of the node to remove
                 */
                function destroyNode(uint256 nodeNum) internal {
                    _nodes[nodeNum].destroy();
                    _nodes[nodeNum] = INode(0);
                }
                function nodeDeadline(
                    uint256 avmGasSpeedLimitPerBlock,
                    uint256 gasUsed,
                    uint256 confirmPeriodBlocks,
                    INode prevNode
                ) internal view returns (uint256 deadlineBlock) {
                    // Set deadline rounding up to the nearest block
                    uint256 checkTime =
                        gasUsed.add(avmGasSpeedLimitPerBlock.sub(1)).div(avmGasSpeedLimitPerBlock);
                    deadlineBlock = max(block.number.add(confirmPeriodBlocks), prevNode.deadlineBlock()).add(
                        checkTime
                    );
                    uint256 olderSibling = prevNode.latestChildNumber();
                    if (olderSibling != 0) {
                        deadlineBlock = max(deadlineBlock, getNode(olderSibling).deadlineBlock());
                    }
                    return deadlineBlock;
                }
                function max(uint256 a, uint256 b) internal pure returns (uint256) {
                    return a > b ? a : b;
                }
                struct StakeOnNewNodeFrame {
                    uint256 currentInboxSize;
                    INode node;
                    bytes32 executionHash;
                    INode prevNode;
                    bytes32 lastHash;
                    bool hasSibling;
                    uint256 deadlineBlock;
                    uint256 gasUsed;
                    uint256 sequencerBatchEnd;
                    bytes32 sequencerBatchAcc;
                }
                struct CreateNodeDataFrame {
                    uint256 prevNode;
                    uint256 confirmPeriodBlocks;
                    uint256 avmGasSpeedLimitPerBlock;
                    ISequencerInbox sequencerInbox;
                    RollupEventBridge rollupEventBridge;
                    INodeFactory nodeFactory;
                }
                uint8 internal constant MAX_SEND_COUNT = 100;
                function createNewNode(
                    RollupLib.Assertion memory assertion,
                    bytes32[3][2] calldata assertionBytes32Fields,
                    uint256[4][2] calldata assertionIntFields,
                    bytes calldata sequencerBatchProof,
                    CreateNodeDataFrame memory inputDataFrame,
                    bytes32 expectedNodeHash
                ) internal returns (bytes32 newNodeHash) {
                    StakeOnNewNodeFrame memory memoryFrame;
                    {
                        // validate data
                        memoryFrame.gasUsed = RollupLib.assertionGasUsed(assertion);
                        memoryFrame.prevNode = getNode(inputDataFrame.prevNode);
                        memoryFrame.currentInboxSize = inputDataFrame.sequencerInbox.messageCount();
                        // Make sure the previous state is correct against the node being built on
                        require(
                            RollupLib.stateHash(assertion.beforeState) == memoryFrame.prevNode.stateHash(),
                            "PREV_STATE_HASH"
                        );
                        // Ensure that the assertion doesn't read past the end of the current inbox
                        require(
                            assertion.afterState.inboxCount <= memoryFrame.currentInboxSize,
                            "INBOX_PAST_END"
                        );
                        // Insure inbox tip after assertion is included in a sequencer-inbox batch and return inbox acc; this gives replay protection against the state of the inbox
                        (memoryFrame.sequencerBatchEnd, memoryFrame.sequencerBatchAcc) = inputDataFrame
                            .sequencerInbox
                            .proveInboxContainsMessage(sequencerBatchProof, assertion.afterState.inboxCount);
                    }
                    {
                        memoryFrame.executionHash = RollupLib.executionHash(assertion);
                        memoryFrame.deadlineBlock = nodeDeadline(
                            inputDataFrame.avmGasSpeedLimitPerBlock,
                            memoryFrame.gasUsed,
                            inputDataFrame.confirmPeriodBlocks,
                            memoryFrame.prevNode
                        );
                        memoryFrame.hasSibling = memoryFrame.prevNode.latestChildNumber() > 0;
                        // here we don't use ternacy operator to remain compatible with slither
                        if (memoryFrame.hasSibling) {
                            memoryFrame.lastHash = getNodeHash(memoryFrame.prevNode.latestChildNumber());
                        } else {
                            memoryFrame.lastHash = getNodeHash(inputDataFrame.prevNode);
                        }
                        memoryFrame.node = INode(
                            inputDataFrame.nodeFactory.createNode(
                                RollupLib.stateHash(assertion.afterState),
                                RollupLib.challengeRoot(assertion, memoryFrame.executionHash, block.number),
                                RollupLib.confirmHash(assertion),
                                inputDataFrame.prevNode,
                                memoryFrame.deadlineBlock
                            )
                        );
                    }
                    {
                        uint256 nodeNum = latestNodeCreated() + 1;
                        memoryFrame.prevNode.childCreated(nodeNum);
                        newNodeHash = RollupLib.nodeHash(
                            memoryFrame.hasSibling,
                            memoryFrame.lastHash,
                            memoryFrame.executionHash,
                            memoryFrame.sequencerBatchAcc
                        );
                        require(newNodeHash == expectedNodeHash, "UNEXPECTED_NODE_HASH");
                        nodeCreated(memoryFrame.node, newNodeHash);
                        inputDataFrame.rollupEventBridge.nodeCreated(
                            nodeNum,
                            inputDataFrame.prevNode,
                            memoryFrame.deadlineBlock,
                            msg.sender
                        );
                    }
                    emit NodeCreated(
                        latestNodeCreated(),
                        getNodeHash(inputDataFrame.prevNode),
                        newNodeHash,
                        memoryFrame.executionHash,
                        memoryFrame.currentInboxSize,
                        memoryFrame.sequencerBatchEnd,
                        memoryFrame.sequencerBatchAcc,
                        assertionBytes32Fields,
                        assertionIntFields
                    );
                    return newNodeHash;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../challenge/ChallengeLib.sol";
            import "./INode.sol";
            import "@openzeppelin/contracts/math/SafeMath.sol";
            library RollupLib {
                using SafeMath for uint256;
                struct Config {
                    bytes32 machineHash;
                    uint256 confirmPeriodBlocks;
                    uint256 extraChallengeTimeBlocks;
                    uint256 avmGasSpeedLimitPerBlock;
                    uint256 baseStake;
                    address stakeToken;
                    address owner;
                    address sequencer;
                    uint256 sequencerDelayBlocks;
                    uint256 sequencerDelaySeconds;
                    bytes extraConfig;
                }
                struct ExecutionState {
                    uint256 gasUsed;
                    bytes32 machineHash;
                    uint256 inboxCount;
                    uint256 sendCount;
                    uint256 logCount;
                    bytes32 sendAcc;
                    bytes32 logAcc;
                    uint256 proposedBlock;
                    uint256 inboxMaxCount;
                }
                function stateHash(ExecutionState memory execState) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                execState.gasUsed,
                                execState.machineHash,
                                execState.inboxCount,
                                execState.sendCount,
                                execState.logCount,
                                execState.sendAcc,
                                execState.logAcc,
                                execState.proposedBlock,
                                execState.inboxMaxCount
                            )
                        );
                }
                struct Assertion {
                    ExecutionState beforeState;
                    ExecutionState afterState;
                }
                function decodeExecutionState(
                    bytes32[3] memory bytes32Fields,
                    uint256[4] memory intFields,
                    uint256 proposedBlock,
                    uint256 inboxMaxCount
                ) internal pure returns (ExecutionState memory) {
                    return
                        ExecutionState(
                            intFields[0],
                            bytes32Fields[0],
                            intFields[1],
                            intFields[2],
                            intFields[3],
                            bytes32Fields[1],
                            bytes32Fields[2],
                            proposedBlock,
                            inboxMaxCount
                        );
                }
                function decodeAssertion(
                    bytes32[3][2] memory bytes32Fields,
                    uint256[4][2] memory intFields,
                    uint256 beforeProposedBlock,
                    uint256 beforeInboxMaxCount,
                    uint256 inboxMaxCount
                ) internal view returns (Assertion memory) {
                    return
                        Assertion(
                            decodeExecutionState(
                                bytes32Fields[0],
                                intFields[0],
                                beforeProposedBlock,
                                beforeInboxMaxCount
                            ),
                            decodeExecutionState(bytes32Fields[1], intFields[1], block.number, inboxMaxCount)
                        );
                }
                function executionStateChallengeHash(ExecutionState memory state)
                    internal
                    pure
                    returns (bytes32)
                {
                    return
                        ChallengeLib.assertionHash(
                            state.gasUsed,
                            ChallengeLib.assertionRestHash(
                                state.inboxCount,
                                state.machineHash,
                                state.sendAcc,
                                state.sendCount,
                                state.logAcc,
                                state.logCount
                            )
                        );
                }
                function executionHash(Assertion memory assertion) internal pure returns (bytes32) {
                    return
                        ChallengeLib.bisectionChunkHash(
                            assertion.beforeState.gasUsed,
                            assertion.afterState.gasUsed - assertion.beforeState.gasUsed,
                            RollupLib.executionStateChallengeHash(assertion.beforeState),
                            RollupLib.executionStateChallengeHash(assertion.afterState)
                        );
                }
                function assertionGasUsed(RollupLib.Assertion memory assertion)
                    internal
                    pure
                    returns (uint256)
                {
                    return assertion.afterState.gasUsed.sub(assertion.beforeState.gasUsed);
                }
                function challengeRoot(
                    Assertion memory assertion,
                    bytes32 assertionExecHash,
                    uint256 blockProposed
                ) internal pure returns (bytes32) {
                    return challengeRootHash(assertionExecHash, blockProposed, assertion.afterState.inboxCount);
                }
                function challengeRootHash(
                    bytes32 execution,
                    uint256 proposedTime,
                    uint256 maxMessageCount
                ) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(execution, proposedTime, maxMessageCount));
                }
                function confirmHash(Assertion memory assertion) internal pure returns (bytes32) {
                    return
                        confirmHash(
                            assertion.beforeState.sendAcc,
                            assertion.afterState.sendAcc,
                            assertion.afterState.logAcc,
                            assertion.afterState.sendCount,
                            assertion.afterState.logCount
                        );
                }
                function confirmHash(
                    bytes32 beforeSendAcc,
                    bytes32 afterSendAcc,
                    bytes32 afterLogAcc,
                    uint256 afterSendCount,
                    uint256 afterLogCount
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                beforeSendAcc,
                                afterSendAcc,
                                afterSendCount,
                                afterLogAcc,
                                afterLogCount
                            )
                        );
                }
                function feedAccumulator(
                    bytes memory messageData,
                    uint256[] memory messageLengths,
                    bytes32 beforeAcc
                ) internal pure returns (bytes32) {
                    uint256 offset = 0;
                    uint256 messageCount = messageLengths.length;
                    uint256 dataLength = messageData.length;
                    bytes32 messageAcc = beforeAcc;
                    for (uint256 i = 0; i < messageCount; i++) {
                        uint256 messageLength = messageLengths[i];
                        require(offset + messageLength <= dataLength, "DATA_OVERRUN");
                        bytes32 messageHash;
                        assembly {
                            messageHash := keccak256(add(messageData, add(offset, 32)), messageLength)
                        }
                        messageAcc = keccak256(abi.encodePacked(messageAcc, messageHash));
                        offset += messageLength;
                    }
                    require(offset == dataLength, "DATA_LENGTH");
                    return messageAcc;
                }
                function nodeHash(
                    bool hasSibling,
                    bytes32 lastHash,
                    bytes32 assertionExecHash,
                    bytes32 inboxAcc
                ) internal pure returns (bytes32) {
                    uint8 hasSiblingInt = hasSibling ? 1 : 0;
                    return keccak256(abi.encodePacked(hasSiblingInt, lastHash, assertionExecHash, inboxAcc));
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface INode {
                function initialize(
                    address _rollup,
                    bytes32 _stateHash,
                    bytes32 _challengeHash,
                    bytes32 _confirmData,
                    uint256 _prev,
                    uint256 _deadlineBlock
                ) external;
                function destroy() external;
                function addStaker(address staker) external returns (uint256);
                function removeStaker(address staker) external;
                function childCreated(uint256) external;
                function newChildConfirmDeadline(uint256 deadline) external;
                function stateHash() external view returns (bytes32);
                function challengeHash() external view returns (bytes32);
                function confirmData() external view returns (bytes32);
                function prev() external view returns (uint256);
                function deadlineBlock() external view returns (uint256);
                function noChildConfirmedBeforeBlock() external view returns (uint256);
                function stakerCount() external view returns (uint256);
                function stakers(address staker) external view returns (bool);
                function firstChildBlock() external view returns (uint256);
                function latestChildNumber() external view returns (uint256);
                function requirePastDeadline() external view;
                function requirePastChildConfirmDeadline() external view;
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface INodeFactory {
                function createNode(
                    bytes32 _stateHash,
                    bytes32 _challengeHash,
                    bytes32 _confirmData,
                    uint256 _prev,
                    uint256 _deadlineBlock
                ) external returns (address);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            import "../arch/IOneStepProof.sol";
            interface IChallenge {
                function initializeChallenge(
                    IOneStepProof[] calldata _executors,
                    address _resultReceiver,
                    bytes32 _executionHash,
                    uint256 _maxMessageCount,
                    address _asserter,
                    address _challenger,
                    uint256 _asserterTimeLeft,
                    uint256 _challengerTimeLeft,
                    ISequencerInbox _sequencerBridge,
                    IBridge _delayedBridge
                ) external;
                function currentResponderTimeLeft() external view returns (uint256);
                function lastMoveBlock() external view returns (uint256);
                function timeout() external;
                function asserter() external view returns (address);
                function challenger() external view returns (address);
                function clearChallenge() external;
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            interface IChallengeFactory {
                function createChallenge(
                    address _resultReceiver,
                    bytes32 _executionHash,
                    uint256 _maxMessageCount,
                    address _asserter,
                    address _challenger,
                    uint256 _asserterTimeLeft,
                    uint256 _challengerTimeLeft,
                    ISequencerInbox _sequencerBridge,
                    IBridge _delayedBridge
                ) external returns (address);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface IOutbox {
                event OutboxEntryCreated(
                    uint256 indexed batchNum,
                    uint256 outboxEntryIndex,
                    bytes32 outputRoot,
                    uint256 numInBatch
                );
                event OutBoxTransactionExecuted(
                    address indexed destAddr,
                    address indexed l2Sender,
                    uint256 indexed outboxEntryIndex,
                    uint256 transactionIndex
                );
                function l2ToL1Sender() external view returns (address);
                function l2ToL1Block() external view returns (uint256);
                function l2ToL1EthBlock() external view returns (uint256);
                function l2ToL1Timestamp() external view returns (uint256);
                function l2ToL1BatchNum() external view returns (uint256);
                function l2ToL1OutputId() external view returns (bytes32);
                function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths)
                    external;
                function outboxEntryExists(uint256 batchNum) external view returns (bool);
                function executeTransaction(
                    uint256 outboxIndex,
                    bytes32[] calldata proof,
                    uint256 index,
                    address l2Sender,
                    address destAddr,
                    uint256 l2Block,
                    uint256 l1Block,
                    uint256 l2Timestamp,
                    uint256 amount,
                    bytes calldata calldataForL1) external;
            }// SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../INode.sol";
            import "../../bridge/interfaces/IOutbox.sol";
            interface IRollupUser {
                function initialize(address _stakeToken) external;
                function completeChallenge(address winningStaker, address losingStaker) external;
                function returnOldDeposit(address stakerAddress) external;
                function requireUnresolved(uint256 nodeNum) external view;
                function requireUnresolvedExists() external view;
                function countStakedZombies(INode node) external view returns (uint256);
            }
            interface IRollupAdmin {
                event OwnerFunctionCalled(uint256 indexed id);
                /**
                 * @notice Add a contract authorized to put messages into this rollup's inbox
                 * @param _outbox Outbox contract to add
                 */
                function setOutbox(IOutbox _outbox) external;
                /**
                 * @notice Disable an old outbox from interacting with the bridge
                 * @param _outbox Outbox contract to remove
                 */
                function removeOldOutbox(address _outbox) external;
                /**
                 * @notice Enable or disable an inbox contract
                 * @param _inbox Inbox contract to add or remove
                 * @param _enabled New status of inbox
                 */
                function setInbox(address _inbox, bool _enabled) external;
                /**
                 * @notice Pause interaction with the rollup contract
                 */
                function pause() external;
                /**
                 * @notice Resume interaction with the rollup contract
                 */
                function resume() external;
                /**
                 * @notice Set the addresses of rollup logic facets called
                 * @param newAdminFacet address of logic that owner of rollup calls
                 * @param newUserFacet ddress of logic that user of rollup calls
                 */
                function setFacets(address newAdminFacet, address newUserFacet) external;
                /**
                 * @notice Set the addresses of the validator whitelist
                 * @dev It is expected that both arrays are same length, and validator at
                 * position i corresponds to the value at position i
                 * @param _validator addresses to set in the whitelist
                 * @param _val value to set in the whitelist for corresponding address
                 */
                function setValidator(address[] memory _validator, bool[] memory _val) external;
                /**
                 * @notice Set a new owner address for the rollup
                 * @param newOwner address of new rollup owner
                 */
                function setOwner(address newOwner) external;
                /**
                 * @notice Set minimum assertion period for the rollup
                 * @param newPeriod new minimum period for assertions
                 */
                function setMinimumAssertionPeriod(uint256 newPeriod) external;
                /**
                 * @notice Set number of blocks until a node is considered confirmed
                 * @param newConfirmPeriod new number of blocks until a node is confirmed
                 */
                function setConfirmPeriodBlocks(uint256 newConfirmPeriod) external;
                /**
                 * @notice Set number of extra blocks after a challenge
                 * @param newExtraTimeBlocks new number of blocks
                 */
                function setExtraChallengeTimeBlocks(uint256 newExtraTimeBlocks) external;
                /**
                 * @notice Set speed limit per block
                 * @param newAvmGasSpeedLimitPerBlock maximum avmgas to be used per block
                 */
                function setAvmGasSpeedLimitPerBlock(uint256 newAvmGasSpeedLimitPerBlock) external;
                /**
                 * @notice Set base stake required for an assertion
                 * @param newBaseStake maximum avmgas to be used per block
                 */
                function setBaseStake(uint256 newBaseStake) external;
                /**
                 * @notice Set the token used for stake, where address(0) == eth
                 * @dev Before changing the base stake token, you might need to change the
                 * implementation of the Rollup User facet!
                 * @param newStakeToken address of token used for staking
                 */
                function setStakeToken(address newStakeToken) external;
                /**
                 * @notice Set max delay for sequencer inbox
                 * @param newSequencerInboxMaxDelayBlocks max number of blocks
                 * @param newSequencerInboxMaxDelaySeconds max number of seconds
                 */
                function setSequencerInboxMaxDelay(
                    uint256 newSequencerInboxMaxDelayBlocks,
                    uint256 newSequencerInboxMaxDelaySeconds
                ) external;
                /**
                 * @notice Set execution bisection degree
                 * @param newChallengeExecutionBisectionDegree execution bisection degree
                 */
                function setChallengeExecutionBisectionDegree(uint256 newChallengeExecutionBisectionDegree)
                    external;
                /**
                 * @notice Updates a whitelist address for its consumers
                 * @dev setting the newWhitelist to address(0) disables it for consumers
                 * @param whitelist old whitelist to be deprecated
                 * @param newWhitelist new whitelist to be used
                 * @param targets whitelist consumers to be triggered
                 */
                function updateWhitelistConsumers(
                    address whitelist,
                    address newWhitelist,
                    address[] memory targets
                ) external;
                /**
                 * @notice Updates a whitelist's entries
                 * @dev user at position i will be assigned value i
                 * @param whitelist whitelist to be updated
                 * @param user users to be updated in the whitelist
                 * @param val if user is or not allowed in the whitelist
                 */
                function setWhitelistEntries(
                    address whitelist,
                    address[] memory user,
                    bool[] memory val
                ) external;
                /**
                 * @notice Updates whether an address is a sequencer at the sequencer inbox
                 * @param newSequencer address to be modified
                 * @param isSequencer whether this address should be authorized as a sequencer
                 */
                function setIsSequencer(address newSequencer, bool isSequencer) external;
                /**
                 * @notice Upgrades the implementation of a beacon controlled by the rollup
                 * @param beacon address of beacon to be upgraded
                 * @param newImplementation new address of implementation
                 */
                function upgradeBeacon(address beacon, address newImplementation) external;
                function forceResolveChallenge(address[] memory stackerA, address[] memory stackerB) external;
                function forceRefundStaker(address[] memory stacker) external;
                function forceCreateNode(
                    bytes32 expectedNodeHash,
                    bytes32[3][2] calldata assertionBytes32Fields,
                    uint256[4][2] calldata assertionIntFields,
                    bytes calldata sequencerBatchProof,
                    uint256 beforeProposedBlock,
                    uint256 beforeInboxMaxCount,
                    uint256 prevNode
                ) external;
                function forceConfirmNode(
                    uint256 nodeNum,
                    bytes32 beforeSendAcc,
                    bytes calldata sendsData,
                    uint256[] calldata sendLengths,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount
                ) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /*
             * @dev Provides information about the current execution context, including the
             * sender of the transaction and its data. While these are generally available
             * via msg.sender and msg.data, they should not be accessed in such a direct
             * manner, since when dealing with GSN meta-transactions the account sending and
             * paying for execution may not be the actual sender (as far as an application
             * is concerned).
             *
             * This contract is only required for intermediate, library-like contracts.
             */
            abstract contract Context {
                function _msgSender() internal view virtual returns (address payable) {
                    return msg.sender;
                }
                function _msgData() internal view virtual returns (bytes memory) {
                    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                    return msg.data;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "./INode.sol";
            interface IRollupCore {
                function _stakerMap(address stakerAddress)
                    external
                    view
                    returns (
                        uint256,
                        uint256,
                        uint256,
                        address,
                        bool
                    );
                event RollupCreated(bytes32 machineHash);
                event NodeCreated(
                    uint256 indexed nodeNum,
                    bytes32 indexed parentNodeHash,
                    bytes32 nodeHash,
                    bytes32 executionHash,
                    uint256 inboxMaxCount,
                    uint256 afterInboxBatchEndCount,
                    bytes32 afterInboxBatchAcc,
                    bytes32[3][2] assertionBytes32Fields,
                    uint256[4][2] assertionIntFields
                );
                event NodeConfirmed(
                    uint256 indexed nodeNum,
                    bytes32 afterSendAcc,
                    uint256 afterSendCount,
                    bytes32 afterLogAcc,
                    uint256 afterLogCount
                );
                event NodeRejected(uint256 indexed nodeNum);
                event RollupChallengeStarted(
                    address indexed challengeContract,
                    address asserter,
                    address challenger,
                    uint256 challengedNode
                );
                event UserStakeUpdated(address indexed user, uint256 initialBalance, uint256 finalBalance);
                event UserWithdrawableFundsUpdated(
                    address indexed user,
                    uint256 initialBalance,
                    uint256 finalBalance
                );
                function getNode(uint256 nodeNum) external view returns (INode);
                /**
                 * @notice Get the address of the staker at the given index
                 * @param stakerNum Index of the staker
                 * @return Address of the staker
                 */
                function getStakerAddress(uint256 stakerNum) external view returns (address);
                /**
                 * @notice Check whether the given staker is staked
                 * @param staker Staker address to check
                 * @return True or False for whether the staker was staked
                 */
                function isStaked(address staker) external view returns (bool);
                /**
                 * @notice Get the latest staked node of the given staker
                 * @param staker Staker address to lookup
                 * @return Latest node staked of the staker
                 */
                function latestStakedNode(address staker) external view returns (uint256);
                /**
                 * @notice Get the current challenge of the given staker
                 * @param staker Staker address to lookup
                 * @return Current challenge of the staker
                 */
                function currentChallenge(address staker) external view returns (address);
                /**
                 * @notice Get the amount staked of the given staker
                 * @param staker Staker address to lookup
                 * @return Amount staked of the staker
                 */
                function amountStaked(address staker) external view returns (uint256);
                /**
                 * @notice Get the original staker address of the zombie at the given index
                 * @param zombieNum Index of the zombie to lookup
                 * @return Original staker address of the zombie
                 */
                function zombieAddress(uint256 zombieNum) external view returns (address);
                /**
                 * @notice Get Latest node that the given zombie at the given index is staked on
                 * @param zombieNum Index of the zombie to lookup
                 * @return Latest node that the given zombie is staked on
                 */
                function zombieLatestStakedNode(uint256 zombieNum) external view returns (uint256);
                /// @return Current number of un-removed zombies
                function zombieCount() external view returns (uint256);
                function isZombie(address staker) external view returns (bool);
                /**
                 * @notice Get the amount of funds withdrawable by the given address
                 * @param owner Address to check the funds of
                 * @return Amount of funds withdrawable by owner
                 */
                function withdrawableFunds(address owner) external view returns (uint256);
                /**
                 * @return Index of the first unresolved node
                 * @dev If all nodes have been resolved, this will be latestNodeCreated + 1
                 */
                function firstUnresolvedNode() external view returns (uint256);
                /// @return Index of the latest confirmed node
                function latestConfirmed() external view returns (uint256);
                /// @return Index of the latest rollup node created
                function latestNodeCreated() external view returns (uint256);
                /// @return Ethereum block that the most recent stake was created
                function lastStakeBlock() external view returns (uint256);
                /// @return Number of active stakers currently staked
                function stakerCount() external view returns (uint256);
                /// @return Node hash as of this node number
                function getNodeHash(uint256 index) external view returns (bytes32);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface ISequencerInbox {
                event SequencerBatchDelivered(
                    uint256 indexed firstMessageNum,
                    bytes32 indexed beforeAcc,
                    uint256 newMessageCount,
                    bytes32 afterAcc,
                    bytes transactions,
                    uint256[] lengths,
                    uint256[] sectionsMetadata,
                    uint256 seqBatchIndex,
                    address sequencer
                );
                event SequencerBatchDeliveredFromOrigin(
                    uint256 indexed firstMessageNum,
                    bytes32 indexed beforeAcc,
                    uint256 newMessageCount,
                    bytes32 afterAcc,
                    uint256 seqBatchIndex
                );
                event DelayedInboxForced(
                    uint256 indexed firstMessageNum,
                    bytes32 indexed beforeAcc,
                    uint256 newMessageCount,
                    uint256 totalDelayedMessagesRead,
                    bytes32[2] afterAccAndDelayed,
                    uint256 seqBatchIndex
                );
                /// @notice DEPRECATED - look at IsSequencerUpdated for new updates
                // event SequencerAddressUpdated(address newAddress);
                event IsSequencerUpdated(address addr, bool isSequencer);
                event MaxDelayUpdated(uint256 newMaxDelayBlocks, uint256 newMaxDelaySeconds);
                /// @notice DEPRECATED - look at MaxDelayUpdated for new updates
                // event MaxDelayBlocksUpdated(uint256 newValue);
                /// @notice DEPRECATED - look at MaxDelayUpdated for new updates
                // event MaxDelaySecondsUpdated(uint256 newValue);
                function setMaxDelay(uint256 newMaxDelayBlocks, uint256 newMaxDelaySeconds) external;
                function setIsSequencer(address addr, bool isSequencer) external;
                function messageCount() external view returns (uint256);
                function maxDelayBlocks() external view returns (uint256);
                function maxDelaySeconds() external view returns (uint256);
                function inboxAccs(uint256 index) external view returns (bytes32);
                function getInboxAccsLength() external view returns (uint256);
                function proveInboxContainsMessage(bytes calldata proof, uint256 inboxCount)
                    external
                    view
                    returns (uint256, bytes32);
                /// @notice DEPRECATED - use isSequencer instead
                function sequencer() external view returns (address);
                function isSequencer(address seq) external view returns (bool);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev Wrappers over Solidity's arithmetic operations with added overflow
             * checks.
             *
             * Arithmetic operations in Solidity wrap on overflow. This can easily result
             * in bugs, because programmers usually assume that an overflow raises an
             * error, which is the standard behavior in high level programming languages.
             * `SafeMath` restores this intuition by reverting the transaction when an
             * operation overflows.
             *
             * Using this library instead of the unchecked operations eliminates an entire
             * class of bugs, so it's recommended to use it always.
             */
            library SafeMath {
                /**
                 * @dev Returns the addition of two unsigned integers, with an overflow flag.
                 *
                 * _Available since v3.4._
                 */
                function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    uint256 c = a + b;
                    if (c < a) return (false, 0);
                    return (true, c);
                }
                /**
                 * @dev Returns the substraction of two unsigned integers, with an overflow flag.
                 *
                 * _Available since v3.4._
                 */
                function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    if (b > a) return (false, 0);
                    return (true, a - b);
                }
                /**
                 * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
                 *
                 * _Available since v3.4._
                 */
                function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                    // benefit is lost if 'b' is also tested.
                    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                    if (a == 0) return (true, 0);
                    uint256 c = a * b;
                    if (c / a != b) return (false, 0);
                    return (true, c);
                }
                /**
                 * @dev Returns the division of two unsigned integers, with a division by zero flag.
                 *
                 * _Available since v3.4._
                 */
                function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    if (b == 0) return (false, 0);
                    return (true, a / b);
                }
                /**
                 * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
                 *
                 * _Available since v3.4._
                 */
                function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                    if (b == 0) return (false, 0);
                    return (true, a % b);
                }
                /**
                 * @dev Returns the addition of two unsigned integers, reverting on
                 * overflow.
                 *
                 * Counterpart to Solidity's `+` operator.
                 *
                 * Requirements:
                 *
                 * - Addition cannot overflow.
                 */
                function add(uint256 a, uint256 b) internal pure returns (uint256) {
                    uint256 c = a + b;
                    require(c >= a, "SafeMath: addition overflow");
                    return c;
                }
                /**
                 * @dev Returns the subtraction of two unsigned integers, reverting on
                 * overflow (when the result is negative).
                 *
                 * Counterpart to Solidity's `-` operator.
                 *
                 * Requirements:
                 *
                 * - Subtraction cannot overflow.
                 */
                function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                    require(b <= a, "SafeMath: subtraction overflow");
                    return a - b;
                }
                /**
                 * @dev Returns the multiplication of two unsigned integers, reverting on
                 * overflow.
                 *
                 * Counterpart to Solidity's `*` operator.
                 *
                 * Requirements:
                 *
                 * - Multiplication cannot overflow.
                 */
                function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                    if (a == 0) return 0;
                    uint256 c = a * b;
                    require(c / a == b, "SafeMath: multiplication overflow");
                    return c;
                }
                /**
                 * @dev Returns the integer division of two unsigned integers, reverting on
                 * division by zero. The result is rounded towards zero.
                 *
                 * Counterpart to Solidity's `/` operator. Note: this function uses a
                 * `revert` opcode (which leaves remaining gas untouched) while Solidity
                 * uses an invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function div(uint256 a, uint256 b) internal pure returns (uint256) {
                    require(b > 0, "SafeMath: division by zero");
                    return a / b;
                }
                /**
                 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                 * reverting when dividing by zero.
                 *
                 * Counterpart to Solidity's `%` operator. This function uses a `revert`
                 * opcode (which leaves remaining gas untouched) while Solidity uses an
                 * invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                    require(b > 0, "SafeMath: modulo by zero");
                    return a % b;
                }
                /**
                 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
                 * overflow (when the result is negative).
                 *
                 * CAUTION: This function is deprecated because it requires allocating memory for the error
                 * message unnecessarily. For custom revert reasons use {trySub}.
                 *
                 * Counterpart to Solidity's `-` operator.
                 *
                 * Requirements:
                 *
                 * - Subtraction cannot overflow.
                 */
                function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                    require(b <= a, errorMessage);
                    return a - b;
                }
                /**
                 * @dev Returns the integer division of two unsigned integers, reverting with custom message on
                 * division by zero. The result is rounded towards zero.
                 *
                 * CAUTION: This function is deprecated because it requires allocating memory for the error
                 * message unnecessarily. For custom revert reasons use {tryDiv}.
                 *
                 * Counterpart to Solidity's `/` operator. Note: this function uses a
                 * `revert` opcode (which leaves remaining gas untouched) while Solidity
                 * uses an invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                    require(b > 0, errorMessage);
                    return a / b;
                }
                /**
                 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                 * reverting with custom message when dividing by zero.
                 *
                 * CAUTION: This function is deprecated because it requires allocating memory for the error
                 * message unnecessarily. For custom revert reasons use {tryMod}.
                 *
                 * Counterpart to Solidity's `%` operator. This function uses a `revert`
                 * opcode (which leaves remaining gas untouched) while Solidity uses an
                 * invalid opcode to revert (consuming all remaining gas).
                 *
                 * Requirements:
                 *
                 * - The divisor cannot be zero.
                 */
                function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                    require(b > 0, errorMessage);
                    return a % b;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../libraries/MerkleLib.sol";
            import "@openzeppelin/contracts/math/SafeMath.sol";
            library ChallengeLib {
                using SafeMath for uint256;
                function firstSegmentSize(uint256 totalCount, uint256 bisectionCount)
                    internal
                    pure
                    returns (uint256)
                {
                    return totalCount / bisectionCount + (totalCount % bisectionCount);
                }
                function otherSegmentSize(uint256 totalCount, uint256 bisectionCount)
                    internal
                    pure
                    returns (uint256)
                {
                    return totalCount / bisectionCount;
                }
                function bisectionChunkHash(
                    uint256 _segmentStart,
                    uint256 _segmentLength,
                    bytes32 _startHash,
                    bytes32 _endHash
                ) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(_segmentStart, _segmentLength, _startHash, _endHash));
                }
                function assertionHash(uint256 _avmGasUsed, bytes32 _restHash) internal pure returns (bytes32) {
                    // Note: make sure this doesn't return Challenge.UNREACHABLE_ASSERTION (currently 0)
                    return keccak256(abi.encodePacked(_avmGasUsed, _restHash));
                }
                function assertionRestHash(
                    uint256 _totalMessagesRead,
                    bytes32 _machineState,
                    bytes32 _sendAcc,
                    uint256 _sendCount,
                    bytes32 _logAcc,
                    uint256 _logCount
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                _totalMessagesRead,
                                _machineState,
                                _sendAcc,
                                _sendCount,
                                _logAcc,
                                _logCount
                            )
                        );
                }
                function updatedBisectionRoot(
                    bytes32[] memory _chainHashes,
                    uint256 _challengedSegmentStart,
                    uint256 _challengedSegmentLength
                ) internal pure returns (bytes32) {
                    uint256 bisectionCount = _chainHashes.length - 1;
                    bytes32[] memory hashes = new bytes32[](bisectionCount);
                    uint256 chunkSize = ChallengeLib.firstSegmentSize(_challengedSegmentLength, bisectionCount);
                    uint256 segmentStart = _challengedSegmentStart;
                    hashes[0] = ChallengeLib.bisectionChunkHash(
                        segmentStart,
                        chunkSize,
                        _chainHashes[0],
                        _chainHashes[1]
                    );
                    segmentStart = segmentStart.add(chunkSize);
                    chunkSize = ChallengeLib.otherSegmentSize(_challengedSegmentLength, bisectionCount);
                    for (uint256 i = 1; i < bisectionCount; i++) {
                        hashes[i] = ChallengeLib.bisectionChunkHash(
                            segmentStart,
                            chunkSize,
                            _chainHashes[i],
                            _chainHashes[i + 1]
                        );
                        segmentStart = segmentStart.add(chunkSize);
                    }
                    return MerkleLib.generateRoot(hashes);
                }
                function verifySegmentProof(
                    bytes32 challengeState,
                    bytes32 item,
                    bytes32[] calldata _merkleNodes,
                    uint256 _merkleRoute
                ) internal pure returns (bool) {
                    return challengeState == MerkleLib.calculateRoot(_merkleNodes, _merkleRoute, item);
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019-2021, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            library MerkleLib {
                function generateRoot(bytes32[] memory _hashes) internal pure returns (bytes32) {
                    bytes32[] memory prevLayer = _hashes;
                    while (prevLayer.length > 1) {
                        bytes32[] memory nextLayer = new bytes32[]((prevLayer.length + 1) / 2);
                        for (uint256 i = 0; i < nextLayer.length; i++) {
                            if (2 * i + 1 < prevLayer.length) {
                                nextLayer[i] = keccak256(
                                    abi.encodePacked(prevLayer[2 * i], prevLayer[2 * i + 1])
                                );
                            } else {
                                nextLayer[i] = prevLayer[2 * i];
                            }
                        }
                        prevLayer = nextLayer;
                    }
                    return prevLayer[0];
                }
                function calculateRoot(
                    bytes32[] memory nodes,
                    uint256 route,
                    bytes32 item
                ) internal pure returns (bytes32) {
                    uint256 proofItems = nodes.length;
                    require(proofItems <= 256);
                    bytes32 h = item;
                    for (uint256 i = 0; i < proofItems; i++) {
                        if (route % 2 == 0) {
                            h = keccak256(abi.encodePacked(nodes[i], h));
                        } else {
                            h = keccak256(abi.encodePacked(h, nodes[i]));
                        }
                        route /= 2;
                    }
                    return h;
                }
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2019, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            interface ICloneable {
                function isMaster() external view returns (bool);
            }
            // SPDX-License-Identifier: Apache-2.0
            /*
             * Copyright 2020, Offchain Labs, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *    http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */
            pragma solidity ^0.6.11;
            import "../bridge/interfaces/IBridge.sol";
            import "../bridge/interfaces/ISequencerInbox.sol";
            interface IOneStepProof {
                // Bridges is sequencer bridge then delayed bridge
                function executeStep(
                    address[2] calldata bridges,
                    uint256 initialMessagesRead,
                    bytes32[2] calldata accs,
                    bytes calldata proof,
                    bytes calldata bproof
                )
                    external
                    view
                    returns (
                        uint64 gas,
                        uint256 afterMessagesRead,
                        bytes32[4] memory fields
                    );
                function executeStepDebug(
                    address[2] calldata bridges,
                    uint256 initialMessagesRead,
                    bytes32[2] calldata accs,
                    bytes calldata proof,
                    bytes calldata bproof
                ) external view returns (string memory startMachine, string memory afterMachine);
            }
            // SPDX-License-Identifier: MIT
            /*
             * @title Solidity Bytes Arrays Utils
             * @author Gonçalo Sá <goncalo.sa@consensys.net>
             *
             * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
             *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
             */
            pragma solidity ^0.6.11;
            /* solhint-disable no-inline-assembly */
            library BytesLib {
                function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
                    require(_bytes.length >= (_start + 20), "Read out of bounds");
                    address tempAddress;
                    assembly {
                        tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
                    }
                    return tempAddress;
                }
                function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
                    require(_bytes.length >= (_start + 1), "Read out of bounds");
                    uint8 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x1), _start))
                    }
                    return tempUint;
                }
                function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
                    require(_bytes.length >= (_start + 32), "Read out of bounds");
                    uint256 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x20), _start))
                    }
                    return tempUint;
                }
                function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
                    require(_bytes.length >= (_start + 32), "Read out of bounds");
                    bytes32 tempBytes32;
                    assembly {
                        tempBytes32 := mload(add(add(_bytes, 0x20), _start))
                    }
                    return tempBytes32;
                }
            }
            /* solhint-enable no-inline-assembly */
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./Proxy.sol";
            import "../utils/Address.sol";
            import "./IBeacon.sol";
            /**
             * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.
             *
             * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
             * conflict with the storage layout of the implementation behind the proxy.
             *
             * _Available since v3.4._
             */
            contract BeaconProxy is Proxy {
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 private constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Initializes the proxy with `beacon`.
                 *
                 * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
                 * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity
                 * constructor.
                 *
                 * Requirements:
                 *
                 * - `beacon` must be a contract with the interface {IBeacon}.
                 */
                constructor(address beacon, bytes memory data) public payable {
                    assert(_BEACON_SLOT == bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1));
                    _setBeacon(beacon, data);
                }
                /**
                 * @dev Returns the current beacon address.
                 */
                function _beacon() internal view virtual returns (address beacon) {
                    bytes32 slot = _BEACON_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        beacon := sload(slot)
                    }
                }
                /**
                 * @dev Returns the current implementation address of the associated beacon.
                 */
                function _implementation() internal view virtual override returns (address) {
                    return IBeacon(_beacon()).implementation();
                }
                /**
                 * @dev Changes the proxy to use a new beacon.
                 *
                 * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
                 *
                 * Requirements:
                 *
                 * - `beacon` must be a contract.
                 * - The implementation returned by `beacon` must be a contract.
                 */
                function _setBeacon(address beacon, bytes memory data) internal virtual {
                    require(
                        Address.isContract(beacon),
                        "BeaconProxy: beacon is not a contract"
                    );
                    require(
                        Address.isContract(IBeacon(beacon).implementation()),
                        "BeaconProxy: beacon implementation is not a contract"
                    );
                    bytes32 slot = _BEACON_SLOT;
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        sstore(slot, beacon)
                    }
                    if (data.length > 0) {
                        Address.functionDelegateCall(_implementation(), data, "BeaconProxy: function call failed");
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "./IBeacon.sol";
            import "../access/Ownable.sol";
            import "../utils/Address.sol";
            /**
             * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
             * implementation contract, which is where they will delegate all function calls.
             *
             * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
             */
            contract UpgradeableBeacon is IBeacon, Ownable {
                address private _implementation;
                /**
                 * @dev Emitted when the implementation returned by the beacon is changed.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
                 * beacon.
                 */
                constructor(address implementation_) public {
                    _setImplementation(implementation_);
                }
                /**
                 * @dev Returns the current implementation address.
                 */
                function implementation() public view virtual override returns (address) {
                    return _implementation;
                }
                /**
                 * @dev Upgrades the beacon to a new implementation.
                 *
                 * Emits an {Upgraded} event.
                 *
                 * Requirements:
                 *
                 * - msg.sender must be the owner of the contract.
                 * - `newImplementation` must be a contract.
                 */
                function upgradeTo(address newImplementation) public virtual onlyOwner {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Sets the implementation contract address for this beacon
                 *
                 * Requirements:
                 *
                 * - `newImplementation` must be a contract.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
                    _implementation = newImplementation;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeacon {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "../utils/Context.sol";
            /**
             * @dev Contract module which provides a basic access control mechanism, where
             * there is an account (an owner) that can be granted exclusive access to
             * specific functions.
             *
             * By default, the owner account will be the one that deploys the contract. This
             * can later be changed with {transferOwnership}.
             *
             * This module is used through inheritance. It will make available the modifier
             * `onlyOwner`, which can be applied to your functions to restrict their use to
             * the owner.
             */
            abstract contract Ownable is Context {
                address private _owner;
                event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                /**
                 * @dev Initializes the contract setting the deployer as the initial owner.
                 */
                constructor () internal {
                    address msgSender = _msgSender();
                    _owner = msgSender;
                    emit OwnershipTransferred(address(0), msgSender);
                }
                /**
                 * @dev Returns the address of the current owner.
                 */
                function owner() public view virtual returns (address) {
                    return _owner;
                }
                /**
                 * @dev Throws if called by any account other than the owner.
                 */
                modifier onlyOwner() {
                    require(owner() == _msgSender(), "Ownable: caller is not the owner");
                    _;
                }
                /**
                 * @dev Leaves the contract without owner. It will not be possible to call
                 * `onlyOwner` functions anymore. Can only be called by the current owner.
                 *
                 * NOTE: Renouncing ownership will leave the contract without an owner,
                 * thereby removing any functionality that is only available to the owner.
                 */
                function renounceOwnership() public virtual onlyOwner {
                    emit OwnershipTransferred(_owner, address(0));
                    _owner = address(0);
                }
                /**
                 * @dev Transfers ownership of the contract to a new account (`newOwner`).
                 * Can only be called by the current owner.
                 */
                function transferOwnership(address newOwner) public virtual onlyOwner {
                    require(newOwner != address(0), "Ownable: new owner is the zero address");
                    emit OwnershipTransferred(_owner, newOwner);
                    _owner = newOwner;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.0 <0.8.0;
            import "../proxy/Initializable.sol";
            /*
             * @dev Provides information about the current execution context, including the
             * sender of the transaction and its data. While these are generally available
             * via msg.sender and msg.data, they should not be accessed in such a direct
             * manner, since when dealing with GSN meta-transactions the account sending and
             * paying for execution may not be the actual sender (as far as an application
             * is concerned).
             *
             * This contract is only required for intermediate, library-like contracts.
             */
            abstract contract ContextUpgradeable is Initializable {
                function __Context_init() internal initializer {
                    __Context_init_unchained();
                }
                function __Context_init_unchained() internal initializer {
                }
                function _msgSender() internal view virtual returns (address payable) {
                    return msg.sender;
                }
                function _msgData() internal view virtual returns (bytes memory) {
                    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                    return msg.data;
                }
                uint256[50] private __gap;
            }
            // SPDX-License-Identifier: MIT
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.4.24 <0.8.0;
            import "../utils/AddressUpgradeable.sol";
            /**
             * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
             * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
             * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
             * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
             *
             * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
             * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
             *
             * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
             * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
             */
            abstract contract Initializable {
                /**
                 * @dev Indicates that the contract has been initialized.
                 */
                bool private _initialized;
                /**
                 * @dev Indicates that the contract is in the process of being initialized.
                 */
                bool private _initializing;
                /**
                 * @dev Modifier to protect an initializer function from being invoked twice.
                 */
                modifier initializer() {
                    require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");
                    bool isTopLevelCall = !_initializing;
                    if (isTopLevelCall) {
                        _initializing = true;
                        _initialized = true;
                    }
                    _;
                    if (isTopLevelCall) {
                        _initializing = false;
                    }
                }
                /// @dev Returns true if and only if the function is running in the constructor
                function _isConstructor() private view returns (bool) {
                    return !AddressUpgradeable.isContract(address(this));
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity >=0.6.2 <0.8.0;
            /**
             * @dev Collection of functions related to the address type
             */
            library AddressUpgradeable {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize, which returns 0 for contracts in
                    // construction, since the code is only stored at the end of the
                    // constructor execution.
                    uint256 size;
                    // solhint-disable-next-line no-inline-assembly
                    assembly { size := extcodesize(account) }
                    return size > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                    (bool success, ) = recipient.call{ value: amount }("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain`call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                  return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.call{ value: value }(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    // solhint-disable-next-line avoid-low-level-calls
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return _verifyCallResult(success, returndata, errorMessage);
                }
                function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            // solhint-disable-next-line no-inline-assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }