ETH Price: $2,051.09 (-3.20%)

Transaction Decoder

Block:
13461694 at Oct-21-2021 02:58:06 PM +UTC
Transaction Fee:
0.09124540538378242 ETH $187.15
Gas Used:
1,197,418 Gas / 76.20179869 Gwei

Emitted Events:

336 TransparentUpgradeableProxy.0x10e0571aafaf282151fd5b0215b5495521c549509cb0de3a3f8310bd2e344682( 0x10e0571aafaf282151fd5b0215b5495521c549509cb0de3a3f8310bd2e344682, 0x00000000000000000000000000000000000000000000000000000000004d1659, 0x46ab7ce953852a141d65d858950366c9049d54501b1494c2271c24ab683656e4, 00000000000000000000000000000000000000000000000000000000004d17d7, 77fedfc233da79e0c8fea4f15c68d7ddd4027879da1d9be020cead9c27ad41af, 000000000000000000000000000000000000000000000000000000000000354e )
337 GasRefunder.RefundedGasCosts( refundee=[Sender] 0xa4b10ac61e79ea1e150df70b8dda53391928fd14, contractAddress=[Receiver] TransparentUpgradeableProxy, success=True, gas=1439441, gasPrice=76201798690, amountPaid=90769086524561872 )

Account State Difference:

  Address   Before After State Difference Code
0x284c1875...5a4B9438b 86.830177191939648989 Eth86.739408105415087117 Eth0.090769086524561872
0x4c6f947A...C874F95Ef
(Arbitrum: Old Sequencer Inbox)
0xa4b10ac6...91928fD14
(Arbitrum: Sequencer)
2.004127147034458448 Eth
Nonce: 10541
2.0036508281752379 Eth
Nonce: 10542
0.000476318859220548
(Ethermine)
1,320.390253231746721946 Eth1,320.391941591126721946 Eth0.00168835938

Execution Trace

TransparentUpgradeableProxy.8a2df18d( )
  • SequencerInbox.addSequencerL2BatchFromOriginWithGasRefunder( transactions=0x0381A707FF0A845A87F8D2830C60B99473186F2CF2493F20836B17B21AE79FC12934E2078018FCCC760000000000000000000000000000000000000000000000000000000000000001000000000000000000000000688576371E9E54186658DB78172D5B403F811824F38D99C138A8EE6E4BE4D8D6AA2D9046157688E473AE7BD0DC8EC3EC60D0C9465C08FA502AD6FA572A829CB40F2C0F4F88D19F6E6B3CED411A62375A8EE8476E000381A907FF82014B845A87F8D2830D15319482AF49447D8A07E3BD95BD0D56F35241523FBAB180095EA7B300000000000000000000000011111112542D85B3EF69AE05771C2DCCFF4FAA26FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE24E29DD75F31E481A5A7BB25F300342F27D10107945FD6CD0DDD8CF012AE48015C8D94F9D36CF08E34F10ABA4EA8482E44BD46AD32246D3F79280C515E461F7000382010907FF8202DB845A87F8D2832DC6C094635EB2C39C75954BB53EBC011BDC6AFAACE115A680DD5B769EE84AEC4C7310A1A22B2C13344EDAD9A4C0B2F0AC3D0B2564D888810228EE4F5F4F8C006C61E353FF0DD14E62C2A685874E4EB93ABDCD8138E74D31FC437D4A870000000000000000000000000000000000000000000000000000000000000168000000000000000000000000000000000000000000000000000000000024C50B00000000000000000000000000000000000000000000000000000000002501CC9CB54BF476678E81881BECEE470EE22B4332CE7EC329DE6713D50747E46272546A86F27E9193590018D5810866F8E593B40C48619D3061B6529F41E3D93705BF000381A907FF82030B845A87F8D28317FD69949F20DE1FC9B161B34089CBEAE888168B44B0346180A9059CBB000000000000000000000000B0B4BD94D656353A30773AC883591DDBABC0C0BA0000000000000000000000000000000000000000000000000DE0B6B3A7640000A28FFFBE401109E430A226BF7C5FF1287BCAE077B1866A887AFBC08F0187BD9C49461A9ECBB9F173F6577FCCE67F652440B8453B29AB456A9BF565C9EB623AD7000382018707FF34845A87F8D2831B8BD8941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED1739000000000000000000000000000000000000000000000000000000001DCD6500000000000000000000000000000000000000000000000002727E65B912C81F3000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000004C5D1029C2C64FC6477529D5A391CA667A514B4C000000000000000000000000000000000000000000000000000000006171851D0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000D4D42F0B6DEF4CE0383636770EF773390D85C61A9F80A1E37F8F4BBCC18E979DDBF63351EC8E837B136C424FD778E596148F0F374558B593DA8DCA8A0376E7E13D3D7165F7268006E21582F0DDBDC759F8AEE299000382012707FF0C845A87F8D2830D8A5C9410541B07D8AD2647DC6CD67ABD4C03575DADE2618031CD52B00000000000000000000000000000000000000000000000019F3C7EF587A3A539000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000617AB94300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000CB4B980000000000000000000000000000000000000000000000000000000000FC38E2A5E18B5103E1F911AC55A41B746B0E3DC9A9FD88AB08061B916E97047ADF38F51D3081ACE0B48A543D8CBEF791386ABBFD53B19EDBCDB2FB8B5FBC7E072B2D000103818807FF36845A87F8D28402FAF0809458B1422B21D58AE6073BA7B28FEE62F704FC25398050F70AF900000000000000000000000000000000000000000000000000000000000005A5C71098C2D0732AE2B5D0D0998505B0DEBD51C5AC14F9968408128A5C1FCACBB95CC9A33E2B52DFF495AA993B5906641AF17FE39D523BA459E740A459A7ABC22E010382020A07FF17845A87F8D28323F3FE947E418A9926C8D1CBD09CC93E8051CC3BBDFE38548254C30A773C9D9C000000000000000000000000B68C0D092842A4A0272867D89245FCD7E7FCA3EB00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000001A39D27C20536E300000000000000000000000000000000000000000000000001A16EF8909F8D0FEB100000000000000000000000000000000000000000000000000000C559EBDEAC000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001455D398326F99059FF775485246999027B31979550000000000000000000000000000000000000000000000000000000000000000000000000000000000000014BB1B69115F8622B8AD8FDC65A890BED680D74A00000000000000000000000000E7AB9CAEBE9B29C163468B0D81368E2A01548F4B5D5F12E3B49C71E294B4F4C04985FEBF404993A872F8DF22E078D745B197766ED8A29138137330B4B160E3CE01038201A707FF1F845A87F8D283184D7994E592427A0AECE92DE3EDEE1F18E0157C0586156480C04B8D59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000C8EE7DBF8CB1D980C107D3DF6357DEAC7DBE9EF0000000000000000000000000000000000000000000000000000000061717F41000000000000000000000000000000000000000000000000000000006AEC9025000000000000000000000000000000000000000000000003D95003EDCF8449720000000000000000000000000000000000000000000000000000000000000042FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80001F482AF49447D8A07E3BD95BD0D56F35241523FBAB1002710FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A000000000000000000000000000000000000000000000000000000000000AB7C9E8FAB0F5D43D69A34582D1EEF6B5D3215B4FA6F83BB6FD0ABD8E1DB1A411E9729A2DACC8D3F2635324EB5801318AC9C6A2A3A89224F2C62957F35CFD403010382018807FF4B845A87F8D2834C4B4094ABBC5F99639C9B6BCB58544DDF04EFA6802F40640311B32755DE00000000000000000000000000000000000000000000000000000000000000C00000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025BABBA20D748BC65796227400000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000C5C59601E9F963EE7250890000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F64E873AF5231DF73E2DF8905CE4F137923D4B0357CF1A6B807B394F2C4F7613D3F73E6F37A635728D25827D53533B7D7BA87E35F4CA16D81B4B197AD3290D70C01036407FF1C845A87F8D2830B3E4494ADA3459C9D5E8D550DC394B071DA4BDB82BA0A82070F9CFC46A4A38641A0C70294D8EAF120D2BEDE903E8B2C0E6C8F026C7DE502BD5E3E9B82ACA6625B00D98F146BEC1590AF3D7EABA5B7F6BD8EE60D25B15F5F67E4000382016707FF1A845A87F8D283210CCD94CF018D59B4728D073BD961ABE6A8024A8F0A3CDB8060DE1A9B000000000000000000000000EE9801669C6138E84BD50DEB500827B776777D28000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000C00000000000000000000000000000000000000000000000D8D726B7177A800000000000000000000000000000000000000000000000000000001CCA4803E9AC00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000144FF3AA332FD6B1EE6023FE71D67F595E5B515EA7000000000000000000000000BE18527E9AE3D601023B80971E58CF13E2901D9D5112F48E0273F594732CE87C75E4764A0050402D3CFD61EF27BDAC698564879130AA2051128F15EF803A206700036707FF23843B9ACA0083130CB9946B7161DDE9B27D81F7FCF85A5DBDE3176BF0E073800B83A7275F01F28609DD23AE2F51C945C3D1BD3E9E358ED37F2DB3DBD175C7CFB9642DB62A27FA1C5FF4CF8B38084A740CB831A560A3BA9B56C6E750BFE6CC6F378AFBEC01036407FF1D842FAF0800830B3E4494D69029748F485F78C44D4A846E6B8547F90AA139090F83EE92A4FC25B29E87831226C403A7E2634D2C64934679CDFC0B204EEFF2B8554C9F02D7432E83861F5E3D8E83F698ED01B1DF479B003325D0AB9F0D77E4D90A01038201A907FF8208D38477359400834C4B40946F4E8EBA4D337F874AB57478ACC2CB5BACDC19C98017357892000000000000000000000000239B50A61C319CED8BEEAFF9F9A7AAADAC0F526B0000000000000000000000003EA9B0AB55F34FB188824EE288CEAEFC63CF908E000000000000000000000000000000000000000000000001BC16D674EC8000000000000000000000000000000000000000000000000000000071AFD498D00000000000000000000000000000544450FFDFA5EA20528F21918E8AAC7B2C73338100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001BC738E32D7C38F3F000000000000000000000000000000000000000000000000000000006172CFC24ED9624E28C4634B743B6E74F9A1AE4F7743D4C42519990159729739AE2CA277683D760F13CBF401D26389F6E731FA32FF767AEFB60B1B0F50140753CADBB3211DF1C730E4A0DDD45DCA3BCB54D0431517CDCB97B1AA11F66154F015C672CAB2010382016807FF69845A87F8D2834C4B4094ABBC5F99639C9B6BCB58544DDF04EFA6802F40640410B32755DE00000000000000000000000000000000000000000000000000000000000000C000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CDE3EFA1AABBBABC9B799C0000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000CBA9A5E44652C9EBFAB7C2000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1AC005B762EF15EC57E49188BA2C272C625C73132DC2D6AB69AF10ED251A24FE21D7A1F17D59FD9796DBB645235E81F8A78604A274A788A2AE1C809579B295FE201038202E707FF0384B2D05E00833D090094E592427A0AECE92DE3EDEE1F18E0157C0586156480AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000144C04B8D59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061717FD00000000000000000000000000000000000000000000000000000000043D670B900000000000000000000000000000000000000000000000003C087663F2CC4310000000000000000000000000000000000000000000000000000000000000042FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000BB8DA10009CBD5D07DD0CECC66161FC93D7C9000DA1000BB882AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C00000000000000000000000000000000000000000000000003C087663F2CC43100000000000000000000000081F95DEDF9BA08C2F68D1BF7868F519B2C100539000000000000000000000000000000000000000000000000000000001C5B7E59C073ADC0B89DD3F9CB23681AE50B931764F92C24E9D50746BF873FA401AFE0210287A5805F16830E574A4229A8CBD0983EF43F45C00E3A17973132BB000382042D07FF82014C845A87F8D2831F2EAD9411111112542D85B3EF69AE05771C2DCCFF4FAA26807C025200000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000461E76A4FE9F27605D4097A646837C32F1CCC31C000000000000000000000000000000000000000000000000AB1A7906CD3940000000000000000000000000000000000000000000000000000000000BD3E2DF090000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020800000000000000000000000C31E54C7A869B9FCBECC14363CF510D1C41FA4430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000104128ACB08000000000000000000000000461E76A4FE9F27605D4097A646837C32F1CCC31C0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000AB1A7906CD39400000000000000000000000000000000000000000000000000000000001000276A400000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000E26B99771C946DBDDBDA2CA962F0FE4F8D5A607FB9A762DDA3E120F1BF806B6750D1ABF76FBCA5B18010FA6884B17CD7DF940D4F651CFEFA4EE056D0C5639DD555CB29A7000381CA07FF826F448506FC23AC00832DC6C09473FE72C9CAA0FAF0E488570D5898984783E728DF801D4E374000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000676600007006003EDE2403CE71087A09E7E69BB3D394A8D319907B24B06E26194B02478D60B6D5BFA22188DF25AB18BD85B26525690387E953B54B10DAD03CB38D265B1EEBBAABD1D1ED5A052AEE010382016907FF8210938477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718A5C00000000000000000000000000000000000000000000000043606CC6F085800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DFF4476D27E45E3454A301C4264C8977EE8107F0B71EA17F1A80787E1D8F600B3E4374E84344A3A3A036E47050A7EE17CBE56C627650B5A46DAEBD28F192F5E6000382014A07FF83016D488443E5FA9E83186A009457469550B9A42D2FD964E67A9DD1DE3D9169B2918091C88C4C00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000061717EED000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DF289B7E95564700000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000D82E67EFF3CCBC10000F6FB21651CE95F3BCD94E9F91E29C0367B5FFE5582204392D7A985E3B65D7737534D62288EFC963AD746FE9E4FF62E9874B207E294287FDDF0D7863A21CC53B901038201A907FF8195845A87F8D2831C611D94E592427A0AECE92DE3EDEE1F18E0157C058615642D0FC04B8D59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000C26EFA8199105D317AD00A2E90BC5EA445A3CF5F0000000000000000000000000000000000000000000000000000000061717FAF000000000000000000000000000000000000000000000000009FDF42F6E48000000000000000000000000000000000000000000000000000000000000B05CB28000000000000000000000000000000000000000000000000000000000000004282AF49447D8A07E3BD95BD0D56F35241523FBAB10001F42F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F000BB8FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB90000000000000000000000000000000000000000000000000000000000007C300CA9C8833A879CCFE056D0043ABBA35EF0D9559F6E2E7E9B52C3EB1255B454D47812870EF92099606F907252A7F40152982AD0A82FB42106561587088908010382016707FF04845A87F8D2832348E894E22D2BEDB3ECA35E6397E0C6D62857094AA26F5280EEA0D7B2000000000000000000000000000000000000000000000000000000000000008900000000000000000000000053E72EFE3B3776C395D99603971F3776D90614490000000000000000000000000000000000000000000000000000000003C5053B00000000000000000000000000000000000000000000000000000000000F5E130000000000000000000000000000000000000000000000000000000003B17E7400000000000000000000000000000000000000000000000000000000617AB9600000000000000000000000000000000000000000000000000000000003A1220500000000000000000000000000000000000000000000000000000000617AB960D968E6D5BB440BE2B4915FC7E1AD51B91DD5EE9A78934C3EBD23EC2FD73663803B7E52DA38368A41BEA8B057C9030B6081560EE0E4C25C6379A29BD76674B2C2010382016807FF35845A87F8D2834C4B4094ABBC5F99639C9B6BCB58544DDF04EFA6802F40640610B32755DE00000000000000000000000000000000000000000000000000000000000000C000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078DEEC0E1467562DCAE60C0000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000CD8562D3D890AD40EEF9CC000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB13C4AE30D5DEA26F1D8297F18BAF1784C9EC7E328553B69D0F3C9484F8AF5CD9D5F72127E940B23F42F085596B5571EA2C3824E67542508F783F3AC29E3FA3262010382012707FF02845A87F8D2831853629418F7402B673BA6FB5EA4B95768AABB8AAD7EF18A804D49E87D000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000233861DCBB130EFDC00000000000000000000000000000000000000000000000000000000617AB96C000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000027329820000000000000000000000000000000000000000000000000000000000000000816479023477C26CF3FCF69BDDAD089C1BD5DD23EB4D1677B5058C354F70AE545B0595DEE26E5C3C5FC1CB7869A950B221E610ABA9E7C32C9593C0B6122A2B96010382036707FF06845A87F8D2831B510794BA12222222228D8BA445958A75A0704D566BF2C8808BDB391364541216BAFFFEEC8EA535BB71FBC927831D059500010000000000000000000200000000000000000000000038D5E7D08C513E083E02D6A324CFEC03DD47320B00000000000000000000000038D5E7D08C513E083E02D6A324CFEC03DD47320B0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC4FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000473C8596589F6310000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC50000000000000000000000000000000000000000000000000000000000000000000013110FF211E4DD9DB01C71C015929A7F26ABE04483C7CB808C4B8730D642F1BB0B4EF12454064E04D055689B2992342C6FE04AB0B1CB313E37119D11E9E71026010382016707FF05845A87F8D2832348E894E22D2BEDB3ECA35E6397E0C6D62857094AA26F5280EEA0D7B2000000000000000000000000000000000000000000000000000000000000008900000000000000000000000053E72EFE3B3776C395D99603971F3776D90614490000000000000000000000000000000000000000000000000000000003C5053B00000000000000000000000000000000000000000000000000000000000F5E130000000000000000000000000000000000000000000000000000000003B17E7400000000000000000000000000000000000000000000000000000000617AB96A0000000000000000000000000000000000000000000000000000000003A1220500000000000000000000000000000000000000000000000000000000617AB96AFFE571B69145195B4BF9193D3782E6A7DC81AA90208A4432476CB626AE109BEC091455186AED39C4E86806C7C1A6EA7100B5B629E40D44D2B686E48505DC3E55000382027007FF6E849622C2D283B258DC94E592427A0AECE92DE3EDEE1F18E0157C05861564881F5125BC0B1EE67300AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000104DB3E219800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000AC9F41A6AF6CECC84903C828CC3742FE586CA37F0000000000000000000000000000000000000000000000000000000061717FD0000000000000000000000000000000000000000000000000000000022A52BD000000000000000000000000000000000000000000000000001F5125BC0B1EE673000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412210E8A00000000000000000000000000000000000000000000000000000000406E87D8851392686859A9D2EA35EE7C979BA8C5C6647767A7BB139BEF606F17709DE68C73607BF1A1330AFCF5AF2CDEBAAB2A3E2787C44FFCF388D8815A43B9000382016907FF8210948477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718A8E00000000000000000000000000000000000000000000000086C7F48B2A98000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B3477E5E9B04149E106D5DB2FFFCCC7597CCF7BEFBF32610B8AA765E117D46CB0FF7F11D3D0455C55A85B2A8E2C002EABC628AAB5453BA38E0E993B8B442EBE90103818707FF19845A87F8D283134C3E948DC3312C68125A94916D62B97BB5D925F84D4AE0800E752702FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85DB582D7503EBBE8CB3DC43BBCB755B95FEA6400F01A6CD979C642B572AE46F399D46DBD57B51CB7F00CAB80F3A2F113534E5FFD19F929EAC5BEC480FDCAA39000382016807FF02845A87F8D2834C4B4094ABBC5F99639C9B6BCB58544DDF04EFA6802F4064050FB32755DE00000000000000000000000000000000000000000000000000000000000000C000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A1293ABD7089C83D0E8810000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000CC18BD22FACD8504EB4AB2000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB151A8A1C21A55DDADF561987FD3B394A65A3267633079B81BEF60211FDD34661F22267BC2C5F9E027F11F29547A9EC0DDA754D0AA5E1F259498EDF12A02D9B162010381A707FF1E845A87F8D2830FEAFB94739CA6D71365A08F584C8FC4E1029045FA8ABC4B80A9059CBB0000000000000000000000008FA7064E90FED4103A8B5D6A823DA09161DEB27400000000000000000000000000000000000000000000000001197B43E58DE00079D24A41D22E2D27F5D4B32C2540EAC0FD396F82CB4264B0E7DA3073F44B66D32DFB9BFFA874894CF8BB2478D0EF85B26448A18E7D07674D2310DF10778D50DA01036707FF1C845A87F8D2830EB43A9462FF5BE795262999FC1EBAC29277575031D2DA2C803D18B91266AB1EC5BA6C8C8C6F14F9EBD43C8DB3957A414D80ECCEC10B2498FAEE0F3A2054E69007978F0A6DFF63295FA6F5F442DA0C8D09339E8877BA359512694E90ED01038201A907FF8208D48477359400834C4B40946F4E8EBA4D337F874AB57478ACC2CB5BACDC19C98017357892000000000000000000000000C593EFF55725339BD9BDCA2795732FF551C136390000000000000000000000003EA9B0AB55F34FB188824EE288CEAEFC63CF908E000000000000000000000000000000000000000000000001E5B8FA8FE2AC0000000000000000000000000000000000000000000000000000007C585087238000000000000000000000000000544450FFDFA5EA20528F21918E8AAC7B2C73338100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001E61E152F09C77D6D000000000000000000000000000000000000000000000000000000006172CFE943CF89E6B29CDE7B27C9190049ADBE2860749B7F13FB215E285FAB4394DE4F2A35F8C702964CA99175117FFCDBE82190F8743627FD14F0896E84CF11F55262730BB5EEBBBEC9C7F98255C6AF9EB858EC51DB6E65BE592E142F1413AE88048125000382016907FF8210958477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718A3B00000000000000000000000000000000000000000000000086CF0F887425000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D8672449A2E6CC06780169485044B08BA4A56A4E6ECB2E3C43E2B9DFEC3C5E067DB580EB17A9AA8C00F9FE16CEAF8591618C3B5E6E7F7B4C4831DFDBC609D56300038203E707FF0C845A87F8D2832AEE4194C36442B4A4522E871399CD717ABDD847AB11FE8880AC9650D80000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002A000000000000000000000000000000000000000000000000000000000000000A40C49CCBE0000000000000000000000000000000000000000000000000000000000004AA6000000000000000000000000000000000000000000000000012495FE93D1C13A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BDFD63DFF0000000000000000000000000000000000000000000000000000000061718002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084FC6F78650000000000000000000000000000000000000000000000000000000000004AA6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C00000000000000000000000000000000000000000000000001744C72105E9F490000000000000000000000004C0273CF96481BB51EE5E20AB8F56D9651F28DBB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064DF2AB5BB000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000BF7C3FC670000000000000000000000004C0273CF96481BB51EE5E20AB8F56D9651F28DBB0000000000000000000000000000000000000000000000000000000055E57FB7E44EC830031BFC27845D92FCCA0B28557C8FB65C5B7F0A69A90013CC5FE36DDF4214DB135D80ACA6D71D7FD01F95951D2551A10AFA665B9E32267776000382016707FF72845A87F8D2831AB9B2941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE500000000000000000000000000000000000000000002F6974ACB46DE418A8403000000000000000000000000000000000000000000000000D576F22F0F37AE6500000000000000000000000000000000000000000000000000000000000000A00000000000000000000000009AE53373072EBDC6A3A668C1CAAD0C40820B899000000000000000000000000000000000000000000000000000000000617185AC00000000000000000000000000000000000000000000000000000000000000020000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB148A9D886A9D68096BA666A472B908328FB2A0048D58A5DD2BE4D662E3E6F7720381BFF3C1AFA2732F26E4C4846F612ACE1BC4D15958C05EB4E792433845E215C000381A707FF1F845A87F8D2831061ED948E0B8C8BB9DB49A46697F3A5BB8A308E744821D280095EA7B3000000000000000000000000F97C707024EF0DD3E77A0824555A46B622BFB500FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF624B3AD3162EC52E83F3B0352EF4D2E32FB1A901609DC6288DCD345340BEB7D3019A36C171FAD0D80EE58FDCFD1B37A0930C93AAA8F05A8512DE0A8BF894ED70003818707FF4D845A87F8D2831180999458B1422B21D58AE6073BA7B28FEE62F704FC25398050F70AF900000000000000000000000000000000000000000000000000000000000004940AFD88AA3153719A48BAE69B728F0D664FA038291B44A758B416BE8850B0310D1054F4360A6B300F2B9FDBD3965582D8E1E7F166590F7BB61D1552EE4B90EF7000036807FF82049A845A87F8D2830C350094249007731E484950EC384E447902EF5823460F4382CCE50C7053BF379D6C3EC0A83736D50382D11AA40299A36951DABE3C31060C8DC596A528C25A941EBFD8F03C70834BFFE7E6D4ACFF858735AAE8409184113B38DEB2BA000382022707FF60845A87F8D2833AA1BF94226CB17A52709034E2EC6ABE0D2F0A9EBCEC10598078FC6DB0000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000000000012A05F2000000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F000000000000000000000000000000000000000000000000000000000075C03600000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000469BBAFEB93480EE4C2CBFF806BC50418833549900000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB14178E303162938F08DCEAC690A62853CBE0243EB755C7E65042F5E44B9683A816D63845555AD3491D8E573491A6C188D2E93ECDF344B3AC5A79CEEBE3DE98E28000381C707FF2F845A87F8D28310296394F4D73326C13A4FC5FD7A064217E12780E9BD62C380D1ABB90700000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000020F7222164000000000000000000000000018E77FEDDA22C36FAEB5F5F0C0D8A801D85965EC7804F057C90912B06F8A2D40F38793DFFE2B5331424D84691E3385965C662F05629707382A2592E21DABBADF486AEC39C15BDCCD3279C406AAC8C872B61086820182010A07FF83016D498443E5FA9E83124F809457469550B9A42D2FD964E67A9DD1DE3D9169B2918091C88C4C00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000061717F1100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000D7DA244DCF5D28E00009BC03A40DD924165621C6994C732ACB34ACC1ECF1D91E47809F2F80C1A8FC4541A544D5F350BFD2EF8E434DA5C85DF0C7B70685BEE41096DF039B4BEE1370221000382016907FF8210968477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718AB3000000000000000000000000000000000000000000000000870F02700A1A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008B0D3F1BF49B4326CE432CE1C659CA0AB85C5320A45FC5BC76D8105C1B5158C83EE25C00931D8F9A6EFE4F5458128A05D7A76DA0B7D7D1F15BE2ED230F31BC3E010381A707FF08845A87F8D283133A4694F4D73326C13A4FC5FD7A064217E12780E9BD62C38018FCCC76000000000000000000000000000000000000000000000000000000000000000900000000000000000000000012549CE9350C6C6F538520B49EDF921972CB944A737C534165BF6A96DBD6C00CDADEAA6F0CF921036494703CFB1EAB857F93E80E364829B851FB963FC7E65A56455C882B61355A62F2C7C01D0D1C5E30F7AA5F2F010381CA07FF826F458506FC23AC00832DC6C09473FE72C9CAA0FAF0E488570D5898984783E728DF801D4E374000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000672A00006F54003EB19C03CBE0C8B25671BC50ABC33F50B9D40FC41C906F0A3AA2F432222DF113619A74D39B327016CB5E05F97370E7BEC96539C107320F0DEA3776DF28584BDB573EA6D5BDADB5000382016907FF8210978477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718AB3000000000000000000000000000000000000000000000001FA9BD01695A2900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C760E1B10D1496BEC25AA5B796DB67E0EEE33741A639D03723296F4E665D25E2020A36CCCCE804BD6670E50B6F105227CEB29FFA4A0C195090BE2730E910D14300038201A907FF8208BD847D2B7500834C4B40942ED6BC5830AD51A0A8FFEDA475DC64E3C35531448036946015000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000E30000000000002CC3DAFC1C8C880001010204006C0001000264541216BAFFFEEC8EA535BB71FBC927831D059500010000000000000000000200000000000000000000052FD947D9E0000000000000004AAFBFD406B288000082AF49447D8A07E3BD95BD0D56F35241523FBAB1FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8030060C31E54C7A869B9FCBECC14363CF510D1C41FA443FF970A61A04B1CA14834A43F5DE4533EBDDB5CC882AF49447D8A07E3BD95BD0D56F35241523FBAB101000000000000000000000000000000000000000000043402B12F090A000000000001F400000000000000000000000000000000000000000000000000000000000B85079D8445DC65738CF8080C6016A749CC2A65CB819E833A8BEE81D5048987414FAFADC6E2F940AF88CA8AAEF4F0C12C5ADF6814E0449E1C64FF4937C556C3010382016A07FF82103D8477359400834C4B40942A8C3BF2F918B6AAA7821E0C33FE33720EAFEBB4051247E97FDE000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001F40000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB123F7DC1411C277037FDB4BB46814B40CBC6AD1A525683FC327A59216645896FD315B355FF321791B548418F4D9B3BFC0A07645458653F48226F6E0C8D2165606010381C707FF20845A87F8D2831AA52294960EA3E3C7FB317332D990873D354E18D764559080F1DC3CC90000000000000000000000000000000000000000000000000C808D00CA3FF1D60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006804095B5AB361A0DC3F90503F65F03918384E2AB0EDB2683E5DE4D942802BCB9FE703C40C5CA702D86D1A24334D8853B660525EFDF09FECC4D1B0D6F90A3D87D2F73619010382010A07FF83016D4A8443E5FA9E83124F809457469550B9A42D2FD964E67A9DD1DE3D9169B2918091C88C4C00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000061717F17000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DEA00CCAB7C86F0000AE03E6E1B771414AA545BD168CD9F959CA979FFC1D92C1C0971CD1981DC40B9C13BF97319C71AE2412493454E6EF879F92D18F5CD4E4948F0D5C782FCB0C0F8A0103818707FF37845A87F8D28311806E9458B1422B21D58AE6073BA7B28FEE62F704FC25398050F70AF9000000000000000000000000000000000000000000000000000000000000059EF5F2E04078C092ED9483D97144986D2FD9B1ED139E8EDE07893D490FABA856540EE3F561B4D5EEA20D75CC9466FBE268A97428963740B195B0BD9F5DA56089BE000382016907FF8210988477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718AB300000000000000000000000000000000000000000000000086F623F988AC80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006D52A55E955081C91696C6D00040EB445E4CE697132734CC517A72E6A7E61474E6B0DA29AEC87E9EAC1431F2A203F997AF97BDD127A47E572B931DE4377607F000382017007FF04845A87F8D283238ABB9433CEB27B39D2BB7D2E61F7564D3DF293440204178803F636EEA2C282DB00EEA0D7B2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000081F95DEDF9BA08C2F68D1BF7868F519B2C10053900000000000000000000000000000000000000000000000003F636EEA2C282DB000000000000000000000000000000000000000000000000003EB006EB84739300000000000000000000000000000000000000000000000003AD949804E0FA0700000000000000000000000000000000000000000000000000000000617AB9930000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070507EBE9D9253AE88472B138E2684D538CB3E6F60D7568CD166B6D20D8B6672209731BC9809B32341D7A528E3533E56B114DC8EEEA4F286CDE7DA5FE1A7B7DC000382016707FF31845A87F8D28316648C941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED17390000000000000000000000000000000000000000000000015AF1D78B58C40000000000000000000000000000000000000000000000000000000000000306077E00000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000BD32CD640547CD7A5CB1563844B45BE455F5A8900000000000000000000000000000000000000000000000000000000617186030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000EE9801669C6138E84BD50DEB500827B776777D28000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9E7CA433CA15C82508F2328575B48B44D7DFE227B2049545173F8394525AE5F7A3E22530F8854769BB4F3A7624A141A66EDBB8164ACC08DB2EEC374D73493FD5C000382016707FF0F845A87F8D2831A7D69941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE500000000000000000000000000000000000000000000000000000000070B2EC800000000000000000000000000000000000000000000000000655454679F4DDE00000000000000000000000000000000000000000000000000000000000000A00000000000000000000000006744734856D7915D7135FA30B92FE99ED06720C4000000000000000000000000000000000000000000000000000000006171858B0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB141C1961CB6CDAAD2694BB528EFD5F5BCA9D6CF61F3B3A827A4B885F05CCD78417572C37E6FEE2FF1EF9DAD2D5D3FB9F852A28494463FA970455F5D0E44AC7CFC010382010707FF0D845A87F8D2830D71319410541B07D8AD2647DC6CD67ABD4C03575DADE2618091695586000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FDAE310000000000000000000000000000000000000000000000000000000000FC090900000000000000000000000000000000000000000000000000000000617AB99C728F3305796A9C4D82FC68FEE6B4B83E441936A4FCB08D8F01140348C487F892743CF546B781DF304998F39C29343A7F4F3154A74489515E31B558585F579F1F010382017007FF80845A87F8D2831B102D94E592427A0AECE92DE3EDEE1F18E0157C058615648805C42986C43B294000414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA0349780000000000000000000000000000000000000000000000000000000000000BB80000000000000000000000008B503184B871674E7788B1CBA0A05C707BA6CDC3000000000000000000000000000000000000000000000000000000006171802700000000000000000000000000000000000000000000000005C42986C43B2940000000000000000000000000000000000000000000000020E32979288D0C7E2700000000000000000000000000000000000000000000000000000000000000000D2904F16F06EE07160321C89DFF5DF5091DBB987B1ECB4850D39CDA4001159902A60849A36E9CC81BF375645EB32778ACA3B64DAA53C2C41C3C0D5F61A37249010382016907FF82014D845A87F8D28323355294E22D2BEDB3ECA35E6397E0C6D62857094AA26F5280EEA0D7B20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000461E76A4FE9F27605D4097A646837C32F1CCC31C0000000000000000000000000000000000000000000000000000000430E234000000000000000000000000000000000000000000000000000000000006E8C52B000000000000000000000000000000000000000000000000000000042369A65D00000000000000000000000000000000000000000000000000000000617AB9A6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003B7ACAAA221E45D1D63D09C48B5E9E8734A2AFF80491A3B8B470B9E59EB981915219A2B63F8AF8F9442654768B5AF11B4A755ED66F894022580C35E1826E1745000382036707FF04845A87F8D2831B510794BA12222222228D8BA445958A75A0704D566BF2C8808BDB391364541216BAFFFEEC8EA535BB71FBC927831D05950001000000000000000000020000000000000000000000009675F179C037443511EAEB8590CCDA815403D4B10000000000000000000000009675F179C037443511EAEB8590CCDA815403D4B10000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC4FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000473CF68046CB5580000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC50000000000000000000000000000000000000000000000000000000000000000000063D5362989B6229860F375E4F46792A752B956B887149FBC260424A82D99FCF96B7F7E0DC5779623042CF801413D34E7029CCDD7401A22B9F0CA54175EF1F56F01036707FF24845A87F8D2830F7E6794480A511030EF8202A55E81CA9129975386DEEBA5804E71D92DDC1610262BDD854F3F5D7E1D91F67F790685742C013CD9895BA81652F82FBD7D00B5530C5E1827D07D56F265B91B4C4361D3C5F9020B89C7797267EE9FB3EE250003818907FF820392847129F706830BBA5E943749C4F034022C39ECAFFABA182555D4508CACCC8032B949A20000000000000000000000000000000000000000000000000000000000000001FD788CF2030739DC09AD2963D84163ADCB94B94DB1A3FF403C6A621A75C62B655FF4D55030924E6E68980BBE6E5F0CEB832971D32847318197F473C551332D71010382012907FF820393847129F7068323A0FD943749C4F034022C39ECAFFABA182555D4508CACCC803D12A85A00000000000000000000000069323BD279F2ED51BFFE88AB8F25A46FC53562BB000000000000000000000000000000000000000000000000059EBA08B47BEA4BC35A7155E65603CEC2DB7ACE1D9BA016FC9354060E7AA549AA03E51E29159C240000000000000000000000000000000000000000000000000010147446799F5B000000000000000000000000000000000000000000000000058814528412E93A00000000000000000000000000000000000000000000000000000000617AB766020EE65FDBD8BA721F95600D3D4ECB447B9C400826762B8E23D4DA4C9CD5DDA320091FACDC5FE9F57A40BC28065182ECD89234DE1085E1613703724E16B12295000381C807FF8180845A87F8D28313BF2A94F4D73326C13A4FC5FD7A064217E12780E9BD62C380D1ABB907000000000000000000000000000000000000000000000000000000000000000B0000000000000000000000000000000000000000000000201996947B9236527C00000000000000000000000080AF73FEEF1B9D0F2EF230A548D752E7DC984646D51958F06408C92A7C9A82C60A3084525A830C555E594E11C86024D67B77392408AC4DADB1D46C6B02370A266D405E20DD732BE0E778A14283EA91CACA7C8262010381A707FF1B845A87F8D283188DA594EE9801669C6138E84BD50DEB500827B776777D2880095EA7B3000000000000000000000000ECBF96DD4FBFD666A849252EC022BF311A4CA002FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51516DAA3446A5F170C93B52E15D4EEBBBD767949E86A80410C948E716465C57304FF6D57090369BB89D4550362ACF3F869594789147293CD96E617B7FC049F400038202A707FF1F845A87F8D2831A608994E592427A0AECE92DE3EDEE1F18E0157C0586156480AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000104414BF389000000000000000000000000031D35296154279DC1984DCD93E392B1F946737B00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000BB8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000617180270000000000000000000000000000000000000000000000000DE0B6B3A76400000000000000000000000000000000000000000000000000000109D52F0D68E7E1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C0000000000000000000000000000000000000000000000000109D52F0D68E7E100000000000000000000000049D56C2020CAAE817C3B493B00E5C6DEC02F140C000000000000000000000000000000000000000000000000000000005AC96AA693C626A85A2AD4BFBF45A15F7BD80A710CA142624EF7861802E02B97525DA4175326D814819C0370D86FF623ED8145F0F81D79F983BF963FA2103738010381A707FF1D845A87F8D28317DA1794FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980A9059CBB000000000000000000000000ADA3459C9D5E8D550DC394B071DA4BDB82BA0A8200000000000000000000000000000000000000000000000000000000070889801E27F7F489953B59A6B45A136C2FBF3AD38248FE6A3FEB285E2DAD69CDACFA1C0C7C65B498F490CA5A2DB96E7F23D8A621FD67213B04D34C4AC4CD395F2DF63A00038201C707FF30845A87F8D283257A54941B02DA8CB0D097EB8D57A175B88C7D8B47997506802195995C0000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000020F72221640000000000000000000000000000000000000000000000000000000000058B5A60000000000000000000000000000000000000000000000000C738C2280FE4C5000000000000000000000000018E77FEDDA22C36FAEB5F5F0C0D8A801D85965EC0000000000000000000000000000000000000000000000000000000061718AB30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BB2AE5599504A7ECC1F97A5212E24BC0EA4C342A8711B37D85521975EFBB5C61B0EC2454A6DC78FD63E4623163F2BDE637A140E79848B8C359961488975455E8D1398281A29B3F8979C159F052ECE466CEB8842077EEBC5347C11585FE0B99A63323207BBC15A16A0A7C00B861D26F364290D811CEA848CE188C4D4C0100432A5000381A707FF1A845A87F8D2831377A694EE338313F022CAEE84034253174FA562495DCC15801E9A6950000000000000000000000000B9255ED9CD8CF52020CBF902C0E72F50109AFF7C000000000000000000000000000000000000000000000000026006DF9E0044078EAC449855418EDFED713DCAE5D52717E8A838ED3036BAB8868F0482D973F9E83F82D76E7AF86F291C4B2745D7B1FF5F4955FCC9AFA2817856ECD5D9D154465F00038203E707FF48845A87F8D2832F641B94C36442B4A4522E871399CD717ABDD847AB11FE8880AC9650D80000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002A000000000000000000000000000000000000000000000000000000000000000A40C49CCBE00000000000000000000000000000000000000000000000000000000000042BF00000000000000000000000000000000000000000000000014F03CDB29A1A9E1000000000000000000000000000000000000000000000000003BB5CCF5D263B500000000000000000000000000000000000000000000000039A47BEDAD2E24F8000000000000000000000000000000000000000000000000000000006171804F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084FC6F786500000000000000000000000000000000000000000000000000000000000042BF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C000000000000000000000000000000000000000000000000006CD0B105D7BD49000000000000000000000000435F623B646A011A7BFD15324F7DCA7A526496B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064DF2AB5BB000000000000000000000000FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A0000000000000000000000000000000000000000000000005A20F383A121C165000000000000000000000000435F623B646A011A7BFD15324F7DCA7A526496B000000000000000000000000000000000000000000000000000000000657D5A117D4BB3FBDCB5945C6937FDFD6546CDC7D948FE646563D10EE70C048C20614F5A86080895BF52518298D07E78E7AEF787D7F5B7742CFC9852E0541A49000382014807FF8184845A87F8D2834C4B4094ABBC5F99639C9B6BCB58544DDF04EFA6802F406480430ED37C00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073A92178B2F75A8CD530ACA5C80000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000E7D0AE1823582E5E6C3A0F9BB0526D380B16EDF4000000000000000000000000000000000000CA2B5DDCD4BE7BF41B4728000000FD9849F447C15BAD951B6AAD5B52F0EF8A9E50F0EC42D8ED040096BD2ABA27221D215091FD8857167B956602A658B0FCA643A5D80BD246D610BDC779C11D569600038202EA07FF82012C845A87F8D28325491F94E592427A0AECE92DE3EDEE1F18E0157C058615640E11AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000144C04B8D59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061717F41000000000000000000000000000000000000000000000000136DCC951D8C0000000000000000000000000000000000000000000000000000136FDE372E754BE8000000000000000000000000000000000000000000000000000000000000005982AF49447D8A07E3BD95BD0D56F35241523FBAB10001F4FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB90001F4FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80001F482AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C000000000000000000000000000000000000000000000000136FDE372E754BE8000000000000000000000000C92F6C5A6A23784EBE11CC876CB8B347EE3E5903000000000000000000000000000000000000000000000000000000006AF5D3BCDC251DB085A751B737A3B6CDA0F702C09C266D57D3FE6642DBDA657242D46CF9BE3719FDE4EA035F9C7496B7D62475EFFC7DE7C9750E63B452155BED00036707FF06845A87F8D2831254E99435AA587ADD7D66781EB6E20221ABE512FAC2227C80E9FAD8EE7B2E333ACB278A81644A373EC2B2A0CB1D54DC535D9AA399DE1032A0DD7763B16D6A1A72A5A77580A212C53948846EDA582EF312192489A6E4F25B7D0DCCFE16010382010707FF3F845A87F8D2832E66EF9495887654D8646C26FAB33F344576E2E74B211256809A3715FF000000000000000000000000ACEDEE0C6982873C1FBF036AC6B1DF37D0072B2D000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000002DA32C6CDF41B11B0103214475ADEB1D91A042210000000000000000000000007F09F13F6B19C2BF92258E6709B7C2CF503EF0FB070C8AA7570F5E7363D6E508D291D20E5E988C6726D8167BA11A118228F7057508CC08F4F731128487C35E8D411459DAEA6CDF8DFC271C5E176B9349D202D916010381C707FF4F845A87F8D283103F7094F4D73326C13A4FC5FD7A064217E12780E9BD62C3808DBDBE6D000000000000000000000000000000000000000000000000000000000000000B000000000000000000000000000000000000000000000009949BEF2C859B92780000000000000000000000009CA1349B23B6D3B9368F90AB06B0B17FE8C7CB86E29431B5953BCE343732892294505941DD10C8318928F9ED03E9E0268C518B00370D01DC4140C94281CC11A41E26CA1743A787BFBAB703FDA5A754EEC967B10100038201C707FF0D845A87F8D283519D8094C36442B4A4522E871399CD717ABDD847AB11FE88808831645600000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0C06FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0DA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BF7ADC20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BF7ADC2000000000000000000000000004C0273CF96481BB51EE5E20AB8F56D9651F28DBB00000000000000000000000000000000000000000000000000000000617180272F917D1571EBD63F749F0B40DF46E4EC898D64FE9C44D1BCCF6ADD50C0EE2C52330B0EC8ACD8D757730AC3EF9B20BE676406713E49EA57E3E30C856D0586FABE010381A707FF01845A87F8D28313A9829411CDB42B0EB46D95F990BEDD4695A6E3FA03497880095EA7B3000000000000000000000000E592427A0AECE92DE3EDEE1F18E0157C05861564FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF657ECB57BE7A316FD55F86128D9BE6057EDB40FEAEAF0B5F4D57B993E32CF607481118DFD66FCAD2074E1428D9885CC8E844A411B9173B0C14EA0BC0FFAF50B2000381A707FF04845A87F8D2831A0A4894839DE324A1AB773F76A53900D70AC1B913D2B38780441A3E7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005C1B25118AA5F19F1465B59CF79E350C7ECCB17A59EF40C0CC9B97EDB9C68EEEB6E10293E821B95441633243E017ECB81B58AE1216E43A3E975631890570E41D372E3D65E905E7DB7C50003818707FF07845A87F8D28310427494E3C10989DDC5DF5B1B9C0E6229C2E4E0862FDE3E801E83409A0000000000000000000000007EBD8A1803CE082D4DE609C0AA0813DD842BD4DB1EEC687C002E20687927878BCD1C87FE2DAC82C7C083A6592B7A627E190347C61A0D5835C1C621CE0E214E1560EBB6EA6B5923E74949E4FDC2F32781D3CBEEFB010382014707FF10845A87F8D2834C4B4094ABBC5F99639C9B6BCB58544DDF04EFA6802F406480430ED37C00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E36C099813BE3F46C48A4F24B400000000000000000000000000000000000000000000000000000000000000000100000000000000000000000001F5C3422056F29675346EDA652737CA48B07FDF000000000000000000000000000000000000CA2B5DDCD4BE7BF41B4728000000E3A33472D1DBE15B1EBD750BFD8A64B15B61A34D6E8208F5D8C64D750C56A86C3F4EF2C936E910C763234AA8C28E4744C4DD898229FF10B435849040BEB90760010382012A07FF25845A87F8D2831E0C4B941B02DA8CB0D097EB8D57A175B88C7D8B4799750682016011F305D7190000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000000000000000000000006BE3B7BA51893FBA794E200000000000000000000000000000000000000000006B599E7D3A16A4879F194000000000000000000000000000000000000000000000001E60E3E6F55480000000000000000000000000000239B50A61C319CED8BEEAFF9F9A7AAADAC0F526B000000000000000000000000000000000000000000000000000000006171862BA31924D3999F4DC1E0AE68DD8C2860012595CE3FB8ADE1710DD3C7CC518E2F5A6D4BC462BD7C07B641723B98B6F51D10054CC85661C8B37AF9DB2C866BB2D60E000382040A07FF820F5685E8D4A51000836ACFC0944B3F43E086790A71270750192472FB61DF7E856680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000038146A5052627722CDDF213E33323FE0000022F0107080300040501020609000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000001C548600000000000000000000000000000000000000000000000000000000001C631F00000000000000000000000000000000000000000000000000000000001C645000000000000000000000000000000000000000000000000000000000001C8FE200000000000000000000000000000000000000000000000000000000001CA51000000000000000000000000000000000000000000000000000000000001CA69D00000000000000000000000000000000000000000000000000000000001CC2C000000000000000000000000000000000000000000000000000000000001CD15F00000000000000000000000000000000000000000000000000000000001CD20D00000000000000000000000000000000000000000000000000000000001CE7020000000000000000000000000000000000000000000000000000000000000004884A865C055FA5F2671F83CCB3F34B40CCC8A4B3D87898CEF5B33142B4E2680F51C9D20CEFFCFFF98C056DE3F88005EB3FD1A031384B436F3DEB5B0EAAF7D5FD07E8A9323781668E8E4DE82072AE0009D83302DC6CC698CB9B95A5003897FFC113015465FA1CA193F66CD40516B7224651DDDA1A0B7A73A793AD8358A52911B2000000000000000000000000000000000000000000000000000000000000000412150A4BED123E48676F257AC2DC99461C8AC484F095C94AEF17B6622DD301801913D7ED845CDA8AE58AFECD4609E8FD17491E581C45121CFD1A5C4B15401ECC33CCEFE1E8B84751CBF0092D877876EC32D5510A88FB72271A1D4C027F32AD75729BA4D4093B6FE355E2C07C030415DBF4B59506188F14F31B9F866B9CC9B904849AAC2D30419D381AD8A475EFBC943DD7151A867E1645DF4AE96A3CC51DFEBE1E1AD7B1E18D2BC7B1F114732E2E58F0DF6E86DCA8F2D1053808AD535D00510A000381CA07FF826F468506FC23AC00832DC6C09473FE72C9CAA0FAF0E488570D5898984783E728DF801D4E374000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000673400006FA5003ED65403CDD0E0C597E852000AC44ED9B7ED2C1571992AA42A457FEBDD550908C0DAF1D6B791B86E380F2F62E896A45EA014440A1E4A5DA3AA410CF05CC16A3EC5659D69D7631400038201C807FF8181845A87F8D28325D865941B02DA8CB0D097EB8D57A175B88C7D8B47997506802195995C0000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000201996947B9236527C000000000000000000000000000000000000000000003D1DD2D1955E3EF0EA8F000000000000000000000000000000000000000000000000114B8929B6DEB3FA00000000000000000000000080AF73FEEF1B9D0F2EF230A548D752E7DC9846460000000000000000000000000000000000000000000000000000000061718ADB0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B80EEFF2FA6ADE630A10479E0C0BC76F53F1D0168202C2973BD119D01854B1B1F553FB142FED87D2D27425B34A059706B084ED125834CD6F06CC453405B722A31E677014E833F4F7F9EE609101FD05D7459C1D2AC0457F4FC5B59B8065C4AE56C5E8879C72AAA6CBFDFD9E49361D5BF2A5ECEADC5E6F464527F663A866D97D0A701038202AF07FF80845A87F8D2831F4D3894E592427A0AECE92DE3EDEE1F18E0157C058615648701ECA85BF6A9DA01AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000144F28C0498000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000001770532603DE458F4344D608B80A0D587A7DD9B6000000000000000000000000000000000000000000000000000000006171804F000000000000000000000000000000000000000000000000000000000158D94000000000000000000000000000000000000000000000000000133E9397A2A2840000000000000000000000000000000000000000000000000000000000000042FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000BB8DA10009CBD5D07DD0CECC66161FC93D7C9000DA1000BB882AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412210E8A00000000000000000000000000000000000000000000000000000000860B0F71CF3C8A40249A3240D0A0C011738F1EA30F324B9982665E6F57C825475002FAFBA2C89FED45E032F14EFAA443062A9B3BCF91A1AA7D3B821288F2D610010382010A07FF83016D4B8443E5FA9E83124F809457469550B9A42D2FD964E67A9DD1DE3D9169B2918091C88C4C00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000061717F57000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DF1D16BDFB1AB40000D6B40813BE006B419615CDAC83559E3DB12A57723C738BF0D184F362BC3CB95F29F3BCAF8F843016E75B9EDFF51866E2620C8CDF5CF3D2AC645E787BAF1077550081A907FF82013A845A87F8D2830D63C494841CE48F9446C8E281D3F1444CB859B4A6D0738C8057F784BA00E622366A8EEE7F26FB2F261C60CA9268F5D4A3FFEB75C6BA6BACBF956EE20617B3CECE568D46DE17C8C9FB5E555184A666186C8C125E31C3421E6C5C2F56ECAC561226AB58C5FB314F92B60631FEDCD93AF86E4B69E74787D295CABB4A351D583EB23FF9105D7CBDDD41965FE5DB909576B43F313961D689865000E04BBA970003820BAE07FF37845A87F8D2833AFCBD9411111112542D85B3EF69AE05771C2DCCFF4FAA2682397B0E7C025200000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE00000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA034978000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000569D327288D8354F16813AFB01BBA0E60C1301F9000000000000000000000000000000000000000000000000146BD17422FCC0000000000000000000000000000000000000000000000000708148F82BF20AEFB700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009A00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000003E0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000146BD17422FCC00000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004D0E30DB00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F9900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000D45C3A746A22016B2AC77210BDC1CBDE2B1AEEE6000000000000000000000000000000000000000000000000146BD17422FCC00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A4B757FED6000000000000000000000000D45C3A746A22016B2AC77210BDC1CBDE2B1AEEE600000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA0349780000000000000000002625A0A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002647F8FE7A000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E00000000000000000000000000000000000000000000000000000000000001E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A40597122400000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA034978000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004470BDB94700000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA034978000000000000000000000000000000000000000000000073FC0BE2D0EEF8CCE70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C00000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000004400000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA034978000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F9900000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA034978000000000000000000000000569D327288D8354F16813AFB01BBA0E60C1301F900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E26B99775C01658E4B749B10CD5F849B610A56ACE200F42805C180B61040E4588E78105170BBBA7E42AC54CCA6FADCCFF7ECEC1DA8938C1EAB16AC2378F80ED0847EEC6B0103818707FF20845A87F8D2831933B59403AC1AA1FF470CF376E6B7CD3A3389AD6D922A74801C4B774B00000000000000000000000000000000000000000000000000000000000000027F3D8A59FEE09DD74B593E3C6EB283586CDF23204AF791AD1A5927AFA855B6D64C79AD6811FA8E984BB5D96959850106EE903CC592244B85C175F7B7F737557B010382016907FF8210998477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480DB3E2198000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718ADB00000000000000000000000000000000000000000000000086F2967AE3E60000000000000000000000000000000000000000000000000000000000097FDE98000000000000000000000000000000000000000000000000000000000000000000005EF4AE4A342743D865D67DDC01C945B27BEE74BAB507DF0FCED15FAFF7D35512C6EE26F679DAA5E3D4CB1D93170F5D88F50F0C4A03B332ECEA7CBD5C60D6A500036407FF2E845A87F8D2830B3E449495F8F46F5F2A7BBF62F832415B91B014B37A92980110255120DAF4C51C95E237AF42AF8F09D7F4CCAB860A6828183A93B094BE32A7837EF3C94CDF9D72C1066BAA19685A2B838E36603F6E7E3051A20291E00E35357401036407FF1B845A87F8D283201899945D0EA9B2A424E29FD86A40A42FEE549431A09427120EBFF70B148D4A53A2CDBB8726DC64A61B3A49E4013486B9090E0C96B98A6DCB671C76792315B1E80D28F71CD12DD89E71A33F3201D5FE390EF354E6D5477A60D60103818707FF61845A87F8D2832A88E494226CB17A52709034E2EC6ABE0D2F0A9EBCEC1059803CA58A010000EE00924700000000000000003B9ACA0000000000035582665E3F92F500B7CBCE936EB7496B8F641E9078DD5C1F30FF130EBD0882AF0D1A01E2A40CDC65EC517C68E33A14DF6589CDCD34BA8248A8CC4935BD1E57C8C19048CF36BD3DB6E5010382016707FF1D845A87F8D2831A957D941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE5000000000000000000000000000000000000000000000023FC9B4281A0060624000000000000000000000000000000000000000000000000001D35A7985509D900000000000000000000000000000000000000000000000000000000000000A00000000000000000000000008A830F105A42E705CFE3A0295DFCFD7259ED4570000000000000000000000000000000000000000000000000000000006171862B0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ED3FB761414DA74B74F33E5C5A1F78104B188DFC00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB183671D4387B83F8A416F21D28C07F67837A7B0CFB8055A75BE5F0F685CD0E1645E03D78FC9F63B9CFE31977FE6490069559B7F193DAF4412721C779B3104D74F0003818707FF0A845A87F8D2831BD545942C044D16287B582D730EA1DC3B7C7DBD103F947F802E17DE7800000000000000000000000000000000000000000000000A57E1C51928880000F8F082E4FAED4C6289381D46760587F01BA9BA86C33795B57DCFF8481AAF8A040721F578AE232845C8FC54661CBE2AEA3ADF63BDF4FE0C377E4EE486B677110E00038202EA07FF82012D845A87F8D28329409F94E592427A0AECE92DE3EDEE1F18E0157C058615642D10AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000144C04B8D59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061717F5B000000000000000000000000000000000000000000000000063EB89DA4ED0000000000000000000000000000000000000000000000000000064371D227726A6F000000000000000000000000000000000000000000000000000000000000005982AF49447D8A07E3BD95BD0D56F35241523FBAB1000BB8DA10009CBD5D07DD0CECC66161FC93D7C9000DA10001F4FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80001F482AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C000000000000000000000000000000000000000000000000064371D227726A6F000000000000000000000000C92F6C5A6A23784EBE11CC876CB8B347EE3E590300000000000000000000000000000000000000000000000000000000E1D45C8587E73653B3E09C56C74A35BD78F811462D103BFE273BE7FF90873F8C0B13267AE47994B6CE9EC0923A5ABBA9EDAEF4E7EADC72FE42AE2657928C92CC010381A707FF02845A87F8D2830FA20F9411CDB42B0EB46D95F990BEDD4695A6E3FA03497880095EA7B3000000000000000000000000E592427A0AECE92DE3EDEE1F18E0157C05861564FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63C92F835C253CE9DC929BC220176C556B158EDC9C2DDDC24930AE853F5ACF67584C659E608DDC4E9CEB8B7796B0C678243DAD0EE1BF6BB78E3091F6B675039000382016707FF49845A87F8D283168D5E94E592427A0AECE92DE3EDEE1F18E0157C0586156480414BF389000000000000000000000000FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000002710000000000000000000000000435F623B646A011A7BFD15324F7DCA7A526496B0000000000000000000000000000000000000000000000000000000006171804F0000000000000000000000000000000000000000000000005CD5800D820BBF4E0000000000000000000000000000000000000000000000000000000009CB2ECB000000000000000000000000000000000000000000000000000000000000000023FF2B8129C533AC9D32D0E12BDC4A47880F7AA6E20FAD03E0AD8FE95E0BB9E558755044175A28A657361A8F56FC1BBE2C6BD93E3321C082226B06C1EDDA2ACE010382018707FF31845A87F8D2831F9A7A941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED173900000000000000000000000000000000000000000000000000000000005949B4000000000000000000000000000000000000000000002BC3599220A19474AFEA00000000000000000000000000000000000000000000000000000000000000A000000000000000000000000018E77FEDDA22C36FAEB5F5F0C0D8A801D85965EC000000000000000000000000000000000000000000000000000000006171862B00000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AFD5A19B287656A34600E469F9B077BED29F4630048A179AA6AA580F2884A7E2B921D796838371EEF814CEF7459D98393061B6EA4578D45917B60E3FF220967646010381A907FF82014E845A87F8D28310720094FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000841CE48F9446C8E281D3F1444CB859B4A6D0738CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89C70794902C9D6BC330EA9223E6BD7B8E78C8CCF5BE1E6D7AAD503A0180F1F349F1EAF98C8DD00447DFF173587F31B65C5A99FC5339113223D31F7A22CF29DA010382046907FF8203B8845A87F8D2831B9FF994BA12222222228D8BA445958A75A0704D566BF2C880945BCEC900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000030000000000000000000000000046A0B4FA58141ABA23185E79F7047A7DFD0FF100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046A0B4FA58141ABA23185E79F7047A7DFD0FF10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100CF3AE4B9235B1C203457E472A011C12C3A2FDE930001000000000000000000190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001D23F0CF300000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000064541216BAFFFEEC8EA535BB71FBC927831D059500010000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000005A131B3CD23BE0B4F7B274B3D237E73650E543D0000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000001D23F0CF30000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3BA65A1F79CF5E5D5BEB03E895B46AEF351627718A893E1EB4E3D5B07CEA5232337F6AD42B3D5CEB246E49CCFDDF4CD7A0AD2CB0A2325C359AE642ACE03D84FCD28DCEF9000381A807FF0985012A05F2008310620394FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000841CE48F9446C8E281D3F1444CB859B4A6D0738CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51D325199D1F690442E18E82BF978C5D62B8B0C505399E2D919FED5A9F24055F26F7E8179ED7C4B2C505539C8C459F1C043D86D84AAFC74AF835A0115477B78A010381A707FF01845A87F8D28313A84194FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980095EA7B30000000000000000000000001B02DA8CB0D097EB8D57A175B88C7D8B47997506FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5422F4525CDDD69617CF76E34CB52219A744D9A7FAA6ADA730A3C9CB92D240A83C7AE43D49425A6FD84E6FD55E5820DD12EE6D219E70DFD5C1467B70EE512884000381A707FF01845A87F8D2831064A99482AF49447D8A07E3BD95BD0D56F35241523FBAB180095EA7B3000000000000000000000000C9FACFA2FC50C9A30C77A2AD14E2DB107D591918FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CC2BE9632BCF078FF7A97609F7AD6026AFE9742A5155D2B5B5423B10AB889C4376BCE273CE15F620DDCCFEFD5EFCE3373C39BCD311A49BE451655D3D8E827CE000381A707FF03845A87F8D2830FA20F9411CDB42B0EB46D95F990BEDD4695A6E3FA03497880095EA7B3000000000000000000000000E592427A0AECE92DE3EDEE1F18E0157C05861564FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41F2C12B6B038FC1E7131FA282B2042E0E108680AEA1DFD7DB4FEF03625BE3D1691581B49C88709E3C25D17B40E384BA4912E4D73C6F203AF615D4DC2B601412010382036707FF03845A87F8D2831B512D94BA12222222228D8BA445958A75A0704D566BF2C8808BDB391364541216BAFFFEEC8EA535BB71FBC927831D0595000100000000000000000002000000000000000000000000B3D76FE71688D957EA7262FA402B413E6021FD99000000000000000000000000B3D76FE71688D957EA7262FA402B413E6021FD990000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC4FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000004712C865C8F73500000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC500000000000000000000000000000000000000000000000000000000000000000000CA122005F1F617BE7A6A580C33EFC89325647B49FB5EB91D2FB064189AF530BE1B57653C19330A2EAFBF79FF57E5A29A07A6A3D71F50E191A5ECC4B0A1AC561A000382012F07FF02845A87F8D2831DBE9D941B02DA8CB0D097EB8D57A175B88C7D8B47997506871387E2CD14285500F305D719000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000000000000000000000000000000000000158D9400000000000000000000000000000000000000000000000000000000001571FD800000000000000000000000000000000000000000000000000136EE2F2740E870000000000000000000000001770532603DE458F4344D608B80A0D587A7DD9B6000000000000000000000000000000000000000000000000000000006171865D8D9AF96817BF2E9D4EF64B83E4335BDCF30CE266B92526DF5593EB8BE04405A919B422072B8269BFF1595CDC96B57174F5382331AD13FB89C7496E5C590C4D72010381A707FF0D845A87F8D28313A95E94FA7F8980B0F1E64A2062791CC3B0871572F1F7F080095EA7B3000000000000000000000000E592427A0AECE92DE3EDEE1F18E0157C05861564FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C2BA116E312A5B1443AC4E392C8E5F2C74911BA6842AFE7A9FF09240E14CAE6395D99F45CF27699D8907D3E055D731F64502746F023B4FC652A8A67DA1E9C2F010381C707FF26845A87F8D2831A59D194F4D73326C13A4FC5FD7A064217E12780E9BD62C3808DBDBE6D000000000000000000000000000000000000000000000000000000000000000B00000000000000000000000000000000000000000000038620F787EA69D948FB000000000000000000000000239B50A61C319CED8BEEAFF9F9A7AAADAC0F526B661B1C95D658CFADB50BF48A9A12E7D22592959490682715FEF7D2C7A5402C603C6A045F0AA80B65A26D0E7A463E021EF5AC2EBCE0ADF4516AFB4244CDD4A45A00038201C707FF1D845A87F8D28325BF36941B02DA8CB0D097EB8D57A175B88C7D8B47997506802195995C0000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000000001AC2D05A5A5416ED900000000000000000000000000000000000000000000032F1C7C2BF57AF483DB00000000000000000000000000000000000000000000000000E6BA2D64F56BA20000000000000000000000001639B5A337C5BE3776558E55B7EC55734FEFAD4D0000000000000000000000000000000000000000000000000000000061718ADB0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B2D5ECF0D7DF92E12C32DA289B289722C73256B1636E2585901A8691AD6603E3C00E5B18A68E11ABBC763CBAC9CB29E4B58DC41F2991A981C452BD3601274A37CA29251895084DB647A01AA8771F0558DF0A0A74CC99193CF2C7CFF97EAF135816785F770956C05728A86C4B1928F9D8EFEC9D1EB662C3719413A9637425C3B470003818907FF8203F1845A87F8D283208638942BF852E22C92FD790F4AE54A76536C8C4217786B800E752702FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7DBDCAC5D2CA157AC85431AF3F696BCBCC388731CDE48B49949E3042E60CE8D44434758ABC1CA8A5B2186F9B61773B5B9563868D40588D78D53306A31F4C0516000381C707FF11845A87F8D2830D60D494F7CA7384CC6619866749955065F17BEDD3ED80BC80A442C8BE000000000000000000000000000000000000000000000001158E460913D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FD88CF14C9E6815B377573589D07487D5D9EB2594EBDB77698A390FCD76933F7476BDE6AF4BAC07C0BCEC049DBB1503CAC847069C113CFA6CCBA679245466AB5008205AA07FF24845A87F8D2832B7F1594C89958B03A55B5DE2221ACB25B58B89A000215E682015911656F3D640000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001E00000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000B000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEC89F360EFA00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002C000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000F1E566FD86668EC0000000000000000000000000000C593EFF55725339BD9BDCA2795732FF551C136390000000000000000000000000000000000000000000000000000000000000080000000000000000000000000FEA7A6A0B346362BF88A9E4A88416B77A57D6C2A000000000000000000000000C593EFF55725339BD9BDCA2795732FF551C13639000000000000000000000000000000000000000000000F1E566FD86668EBFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C593EFF55725339BD9BDCA2795732FF551C13639000000000000000000000000000000000000000000000001DEC89F360EFA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000C593EFF55725339BD9BDCA2795732FF551C136390000000000000000000000000000000000000000000000000000000000000000185801FA4501D2750288D746B11894BC0E795B712E9D4269A4E4EE21A096DA8E2562F9A246A1761A3A567D51191B78DDC1F7F0CF02BC2F02BB4338129C60778C000382014907FF82014F845A87F8D28323B00694841CE48F9446C8E281D3F1444CB859B4A6D0738C8046B40027000000000000000000000000C75A0FF40DB54203D66BFF76315ED25D66037CE1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000007A61847709E2BDAAA1A03DB906B3DB2042408365693681A9A184B16F2FD8B397FA17DACC9000000000000000000000000000000000000000000000000000000006172D0F70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000461E76A4FE9F27605D4097A646837C32F1CCC31C3F18319E4D4E0E6340A740954FD9F1EF4B8C369E4C76AE4BFF3EABA9B3AF613D71FC35DAA142A451AE9AFB8C02A698BAC514F6797B73356588866EBCA28A2E06010381A907FF8203B9845A87F8D2830CA5A694FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B300000000000000000000000070988060E1FD9BBD795CA097A09EA1539896FF5D000000000000000000000000000000000001BC16D674EC7FF21F494C589C0000F871ED2F59DE2F48FC99406BE752F57AEF2F923DF9098EBBFD6D1A07E38DD6C94E5FF2B177AC126B7E33569B811BCB7B4BDFEC6DBE5FF92ED137F8826F5F3C5F000382036707FF03845A87F8D2831B50F794BA12222222228D8BA445958A75A0704D566BF2C8808BDB391364541216BAFFFEEC8EA535BB71FBC927831D0595000100000000000000000002000000000000000000000000C5B08AC5AB92D249B7EFF11C2CF8828CF44AD276000000000000000000000000C5B08AC5AB92D249B7EFF11C2CF8828CF44AD2760000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC4FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000471338CC3E6ACE40000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC500000000000000000000000000000000000000000000000000000000000000000000761D9236A8E64E02591829E10E2140064FFFF2153C831F2E73F03D3686FA650F2ACFA0955367027A97F371013C64F37ABACEDA8670CF323B940B483B60EF1622010382014A07FF820233845A87F8D2831A1D5D941B02DA8CB0D097EB8D57A175B88C7D8B4799750601107FF36AB50000000000000000000000000000000000000000000000000005FEC94A58B71900000000000000000000000000000000000000000000000000000000000000800000000000000000000000004408E04E4D8AEB7EDBC0BC0AE66028762FDF29E5000000000000000000000000000000000000000000000000000000006171865D000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000739CA6D71365A08F584C8FC4E1029045FA8ABC4BB4625F866FC50F41EA71A566B0DC59435EEFA9520DCF424E4BFDF8218446F7CA240996E47EEFBC82CB29047B0D6356F1E8C8B5F71A69B710DA15A088120B6409010381A807FF0A85012A05F2008310620394FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000841CE48F9446C8E281D3F1444CB859B4A6D0738CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57816D478D249E285BAE17769C834BDD568A9E04EFA104C7DBB02E5F525B43A93ADF6477B7DD8BAB08D88A6401DAECA0BD396B5FA089093DD4023ECC549BC7D90103818907FF8203F2845A87F8D283210B409417933112E9780ABD0F27F2B7D9DDA9E840D4315980852A12E30000000000000000000000000000000000000000000000056BC814E9B84A70000BF54253643AE95CAA520F6E10AE3438024521378A056A017E93823F2DF773AB30784A620563BEC170A1290AEF945F162FE35060BC22807EE980EA411CB57EB5010382010A07FF83016D4C8443E5FA9E83124F809457469550B9A42D2FD964E67A9DD1DE3D9169B2918091C88C4C00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000061717F8900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000D8395E94C4494B10000A5FE104EB51F68E4EF10215C610B6E0F325CDE65C9CCC1A3D4CFE60D09BB3A6279DD86AFA8007479F841EACFE2154E5D0F646EC431FE32FDCD38F1A5FF57928C010382016707FF32845A87F8D2831B317B941B02DA8CB0D097EB8D57A175B88C7D8B4799750680E8E337000000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000000000000000002BFB5DC8C012834329550000000000000000000000000000000000000000000000000C731A1755B0857D000000000000000000000000000000000000000000002BC311CB9626E6722F860000000000000000000000000000000000000000000000000C632A99C72E5BDC00000000000000000000000018E77FEDDA22C36FAEB5F5F0C0D8A801D85965EC000000000000000000000000000000000000000000000000000000006171865DB9AC94DFD8EB1FE25B83BC4C710AB03C798D7082D4A70B774D50AF4DB8F2A3FF5AF79291DEEE9A753FE0D50BFB9624D0408C2A11D0274239681CC96BEB248E550003820DCB07FF1E845A87F8D28348DA0C9411111112542D85B3EF69AE05771C2DCCFF4FAA26807C025200000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001800000000000000000000000004E352CF164E64ADCBAD318C3A1E222E9EBA4CE42000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000D50735819DDDDEA6BDEFE7B258B5B88D21DDA93900000000000000000000000000000000000000000000001B1AE4D6E2EF50000000000000000000000000000000000000000000000000000000000006A11020320000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BC00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000092080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064EB5625D90000000000000000000000004E352CF164E64ADCBAD318C3A1E222E9EBA4CE42000000000000000000000000BA12222222228D8BA445958A75A0704D566BF2C800000000000000000000000000000000000000000000001B1AE4D6E2EF50000000000000000000000000000000000000000000000000000000000000800000000000000000000000BA12222222228D8BA445958A75A0704D566BF2C800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001E452BBBE2900000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000006172D106B5B77F1AD2B520DF01612399258E7787AF63025D00020000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004E352CF164E64ADCBAD318C3A1E222E9EBA4CE4200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000001B1AE4D6E2EF50000000000000000000000000000000000000000000000000000000000000000000C0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000164B3AF37C00000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000000400000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000010000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000242E1A7D4D00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001E4B3AF37C000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000044000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE0000000000000000000000000000000100000000000000000000000000000001800000000000000000000000960EA3E3C7FB317332D990873D354E18D764559000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A4394747C5000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F99000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000D50735819DDDDEA6BDEFE7B258B5B88D21DDA93900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E26B99772BF7A2E13093B376F21F6087710ED2B491A5637345C0EF2123CC05B63564491E07922CBC7FC54BCC2BF8669AB619A811A213D77E62BA9EB09431C8B9AD2227A6000382020907FF8208BE847D2B7500834C4B40942ED6BC5830AD51A0A8FFEDA475DC64E3C35531448036946015000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001460000000000000B23822D1014BB8001010304006C00010000B5B77F1AD2B520DF01612399258E7787AF63025D0002000000000000000000100000000000001FFF1D13893B5E000000000000000000004C76CEE6C94C18000082AF49447D8A07E3BD95BD0D56F35241523FBAB14E352CF164E64ADCBAD318C3A1E222E9EBA4CE42030060CB7A3A9E1A057744A60D8103EE66DD28A71C4D754E352CF164E64ADCBAD318C3A1E222E9EBA4CE42FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000080B734E3C31438000000000BB8030060C31E54C7A869B9FCBECC14363CF510D1C41FA443FF970A61A04B1CA14834A43F5DE4533EBDDB5CC882AF49447D8A07E3BD95BD0D56F35241523FBAB10100000000000000000000000000000000000000000004350FA82887B2000000000001F40000000000000000000000000000000000000000000000000000BA0A91578AF3D576A10724A9DAA04BD3C504DAA06D6BBDDDCC6DE087EEF2DA755D029EEFA148FE4CD9973B0085F6A9D79E28F99AF1F27C5FEC95CAAC1BC15A690081A907FF82064A8477359400834C4B409424C4F5E7A271831264BB4C1458BE96007C25FFB8802CBE4E950000000000000000000000000000000000000000000004B55201F654838000000000000000000000000000000000000000000000000000000000000000000001BF7ABB6BF38691E151464D50D9B812EC605137DD4FB77E2C0B17BF528B5E981F2FA4F121D46C335303F7CEEF4D326E9E189B9B99BA02521EBD3D7EDE6262262A010381A807FF8196845A87F8D28310697494FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980095EA7B3000000000000000000000000E1B8800C33672A495AE2CBC882C14E7C9438166CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA5019ECEAB4CF896D058EAD307E455D41E779609873B9240C52D70F2F1E4804726695AFADBA32296B8F1D594017EC645F842D5F1FFAF2864538B21DF6C5B9DE0103818707FF1C845A87F8D2831BD78994B84BE0E36857FAC42FA16193629DE5456689F64B80A694FC3A00000000000000000000000000000000000000000000054A90DD1673A56D000029594F5E86DBBED367A9B2322A3501A7FE9EA68F79FF795678D3A284AEB4EAE91043FB1998D7BE63E3EFFEA3236972EB821C0F0791AB4C3584BF69B338E62B7B000382016707FF32845A87F8D2831ADCC6941B02DA8CB0D097EB8D57A175B88C7D8B4799750680E8E33700000000000000000000000000EE9801669C6138E84BD50DEB500827B776777D28000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB90000000000000000000000000000000000000000000000016B944228D7C9EEA000000000000000000000000000000000000000000000000000000000033186E800000000000000000000000000000000000000000000000169C2E08C7A8CC33100000000000000000000000000000000000000000000000000000000032D70780000000000000000000000000BD32CD640547CD7A5CB1563844B45BE455F5A89000000000000000000000000000000000000000000000000000000006171865D1258DEE376B17B41D69A8D94ACFF096093DA09E61703678BDB8E507D5037A40010ABBAD938B95EA99A861D1C6815CCD20A1F0BDD7344125551165EB95FC89B2B00038202D007FF6F849622C2D283EA028394C36442B4A4522E871399CD717ABDD847AB11FE8888261DF1F2767DC9DE00AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001E000000000000000000000000000000000000000000000000000000000000001648831645600000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0C4CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0F62000000000000000000000000000000000000000000000000261DF1F2767DC9DE000000000000000000000000000000000000000000000000000000022E8F286C00000000000000000000000000000000000000000000000021ACE2A0E9A254C800000000000000000000000000000000000000000000000000000001DFB6F1C9000000000000000000000000AC9F41A6AF6CECC84903C828CC3742FE586CA37F000000000000000000000000000000000000000000000000000000006171808100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412210E8A00000000000000000000000000000000000000000000000000000000CBAC89FD6677EBCDF5388AE4B3959148F9E2BBC785D54FA820958E3D5ABE78F26DF66292E9A2A652091C8B40DA75CA22E6A1D1C250BBA71DF602CA2CFA811B62000382036707FF03845A87F8D2831B511194BA12222222228D8BA445958A75A0704D566BF2C8808BDB391364541216BAFFFEEC8EA535BB71FBC927831D0595000100000000000000000002000000000000000000000000C358EBA833D3E62075F0235B23DF0B6CCEFCF088000000000000000000000000C358EBA833D3E62075F0235B23DF0B6CCEFCF0880000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC4FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000004713A934707C7A00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC5000000000000000000000000000000000000000000000000000000000000000000004B27C30BF036B5F3E11F00ECEF3CCC6DB4042AE9DFF396A4EC7D5B5BFF8FB3CA1675D2A6DE02BBFFA946F2D3207DE560B1421EDE905C9ACA2D5F408BC52FA0D0010382016707FF1E845A87F8D2831695B2941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED17390000000000000000000000000000000000000000000003348EA15554F56D10C000000000000000000000000000000000000000000000000000E66AE77BC2204000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000001639B5A337C5BE3776558E55B7EC55734FEFAD4D000000000000000000000000000000000000000000000000000000006171865D00000000000000000000000000000000000000000000000000000000000000020000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB12050029A8F2E85B3BE5CDC319B86A8801546E2F7116AD1994C31C5EF6607B47878671000E8BCC62D3A507A779AE728CEDCF838E93FB9D96A2C7BCCB57F3D93A9000382018707FF10845A87F8D2831FB8DD941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED173900000000000000000000000000000000000000000000000AC5BCFDE364BF3FE90000000000000000000000000000000000000000000002552174B9397C0938EE00000000000000000000000000000000000000000000000000000000000000A00000000000000000000000006744734856D7915D7135FA30B92FE99ED06720C4000000000000000000000000000000000000000000000000000000006171865D0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000FEA7A6A0B346362BF88A9E4A88416B77A57D6C2A00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00C001141293783F72462011729DBEB3409A4E4157264B148561642A5F01245D57692D5184DDD99D2AD2417DAF13C48E39E21ABE2BCE8AAE7848A8EB63005F6200036907FF82019E845A87F8D2833D0900948156E45DDD85FF1E6D013D0AE3424BBE20596AC3804641257D98E7F8D1566CC13F2AC045BCB9B00C131511E4B7ABBF3FACE6D8108C6F9779361EC1900D5D47CA35666131411603D23998FF20F38832ECE55BC1C504754E2BFF000382016707FF05845A87F8D2831C920494E22D2BEDB3ECA35E6397E0C6D62857094AA26F5280EEA0D7B20000000000000000000000000000000000000000000000000000000000000089000000000000000000000000E1C8E869BD1B82BA5BA39593E001D8A1D3893F13000000000000000000000000000000000000000000000000000000000318C46800000000000000000000000000000000000000000000000000000000000F5E13000000000000000000000000000000000000000000000000000000000301FE9B00000000000000000000000000000000000000000000000000000000617ABA090000000000000000000000000000000000000000000000000000000002F1EDAC00000000000000000000000000000000000000000000000000000000617ABA09A7CEC1B92757673465388B5769596974098FDF77EE1582801EC95A7F5DB49DC561E9696930ABB0801E37DF444FBBF3928F8E52B3AD614BEA0A4813AEF006134801038202AF07FF80845A87F8D2831F45ED94E592427A0AECE92DE3EDEE1F18E0157C0586156487134E03C7FE0C4700AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000144F28C0498000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000051E0DCF9C00CBFB82C1E20220F48E1F5C1272910000000000000000000000000000000000000000000000000000000006171804F000000000000000000000000000000000000000000000000000000000158D94000000000000000000000000000000000000000000000000000134E03C7FE0C470000000000000000000000000000000000000000000000000000000000000042FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000BB8DA10009CBD5D07DD0CECC66161FC93D7C9000DA10001F482AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412210E8A00000000000000000000000000000000000000000000000000000000CD0474B25F2B918EF2436AA553C5E687A844AA048BE021F854D6FC07FDB5F95A09F78E05BAC4269D979A029BC7DF80C7637F820C98AEDD6BD40CDEF9A5118F92000381C707FF33845A87F8D2831A447D94F4D73326C13A4FC5FD7A064217E12780E9BD62C3808DBDBE6D000000000000000000000000000000000000000000000000000000000000000B000000000000000000000000000000000000000000000016FCF1A97FC879AF3400000000000000000000000018E77FEDDA22C36FAEB5F5F0C0D8A801D85965EC93C5B326AE206012A536D46FC7C5DDEF5A6A3B04F2FEEFEE5A41EDEB4983C8B22B9CBA127C6D9F8B2A445F85BFB1624D2DB359AEFACD82649967F0EA12B00DCA01038202A707FF04845A87F8D2831A7C8E94E592427A0AECE92DE3EDEE1F18E0157C0586156480AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000104414BF38900000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA03497800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000BB800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061718081000000000000000000000000000000000000000000000020EB94C75C0C2A751000000000000000000000000000000000000000000000000005B9DF655B40243A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C00000000000000000000000000000000000000000000000005B9DF655B40243A0000000000000000000000008B503184B871674E7788B1CBA0A05C707BA6CDC3000000000000000000000000000000000000000000000000000000008D88B1FD75284ADAF2590111FD4226BD632538EE518F02AAA92CDBE3EBCA41FA717603990041EB2C4365EACF6FEBD398EED607FB5D01EEEB77F4CD291190FF7500038203EA07FF8208A28502540BE400839896809448CC730900C9B7BDADD2AF2F3BE40C09DDFCE34A8070D2939F000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002C0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000006BD74B53F847DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000011CDB42B0EB46D95F990BEDD4695A6E3FA034978000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000E592427A0AECE92DE3EDEE1F18E0157C05861564000000000000000000000000530476D5583724A89C8841EB6DA76E7AF4C0F17E0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000A95B0F5A65A769D82AB4F3E82842E45B8BBAF101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000BB800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000013DE2D89F5363F85378937F421BA08F4278ADDA9F31233DEBAE232C2AB00497D719AD706DA646AA5F1AF5A7A93F39220CE7F0DF82A97E14E9637FB8512B99450901036707FF29845A87F8D2830ED0549435AA587ADD7D66781EB6E20221ABE512FAC2227C80B88A802FFB102A9D58EE52A5E2D9158048264D0577DA8B64806C2DBE72DACFCBB775E2C8313C35EA93D82C56760E2CBEC18AEF7527AA05BA3C9F4FB9752F94119295557400036707FF38845A87F8D2830B686F94C6D714170FE766691670F12C2B45C1F34405AAB680F69E20466D69AB0415BCA42BC1152F18482A020FA454E3E2DCAB500BC5A92C3EE31FE18A6D15F7E2BAB0F3A0AF80B7B7F84241CAF774A5F452A8A6E16C840AE75E9903C6000382014807FF0B85012A05F2008323A61A94841CE48F9446C8E281D3F1444CB859B4A6D0738C8046B40027000000000000000000000000C75A0FF40DB54203D66BFF76315ED25D66037CE1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000009C91FDF95850B19099F2F360977A9F3C31567E83B66D1E809F560AEECE2E2A5CF2209D250000000000000000000000000000000000000000000000000000000006172D116000000000000000000000000000000000000000000000000000000000000A86A0000000000000000000000002AF11C446929A061F8209EF8BDA193AEADD2C6BEAE6FED6996764B42DDF0D57F43F36E894A914B904FB19792C5C3A8FDFC2FBAC3284FC0328D777EE0B8C1C9DB40A2C00BDC252BF5D84B34D36A28B0635735E581010382016707FF4B845A87F8D2831A896C941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE5000000000000000000000000000000000000000000000003CB71F51FC558000000000000000000000000000000000000000000000000000000CA728F835E246D00000000000000000000000000000000000000000000000000000000000000A00000000000000000000000008E7C5F79B23F46511C9A680FAB7BA54F4A6C1452000000000000000000000000000000000000000000000000000000006171862B00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000F4676178B5C53AE0A655F1B19A96387E4B8B5F200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1D0BDF66E10FC3D50378878CE590249DA639B60800F88786032F55157B882719646DACA99288A0804BC089F6CA7F1996697DCFFA58042985C55A2719B50DE97B3010382010707FF40845A87F8D28315427F9499CF05461DD5F94761D4FAE6A2ABDA47A93451F58031C1ABDC0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ACEDEE0C6982873C1FBF036AC6B1DF37D0072B2D0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000BDEB3A7CCF96096AEA9CBF4F1A55D30CC16275400000000000000000000000009C912D53522CCC6BF1687A5A6A2A79FEC8FFAC251C540B382E3AB161A2ECED23995F8116ECC71E99B0620FC554C0125A674E509A3CB98782C702C7B4C8909648EE68E2E0CB1CD56A9F4D5A9315111CBEE6FCCF68000381A707FF01845A87F8D28313A82D94FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980095EA7B30000000000000000000000001B02DA8CB0D097EB8D57A175B88C7D8B47997506FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED3B7507E55B150CC9F2649F6E7B14B63A3DD7CFF5BE43DF237F3446CF650686362A7860C093CDADB872A2F686705D936188C9FA5AD0470B06D0AFAE23DD0E75000382018807FF03845A87F8D2834C4B4094ABBC5F99639C9B6BCB58544DDF04EFA6802F40640110B32755DE00000000000000000000000000000000000000000000000000000000000000C000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000277A22476B50766A4BB5C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA6DCBDB1CEAE8388C3FA4000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8A7F31DC145B3F8E5D308D551D7A19D8F16A0524976CBCF5A2ECD897EB5CA503B220265077D7E5395B7BD623410084C767BCC10A6FDB5F69C27BE6D3AB61A663B000382036707FF03845A87F8D2831B511194BA12222222228D8BA445958A75A0704D566BF2C8808BDB391364541216BAFFFEEC8EA535BB71FBC927831D0595000100000000000000000002000000000000000000000000AEB34E4CA2F648F95F260EE04BD4C0E2EC8C09D0000000000000000000000000AEB34E4CA2F648F95F260EE04BD4C0E2EC8C09D00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC4FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000004714199E5F3455D0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC500000000000000000000000000000000000000000000000000000000000000000000AD51879B03D40F51B674AEE27BD5A2310BFD814F6C1586493995AE43DB274890676E4792F1C20C1C82122331D965D1EA31113B317445771D50EAD194C5B86DE8000382016707FF21845A87F8D2831A916D941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE50000000000000000000000000000000000000000000000001F26AE1C4033673D00000000000000000000000000000000000000000000000000348E8305C5595A00000000000000000000000000000000000000000000000000000000000000A000000000000000000000000049D56C2020CAAE817C3B493B00E5C6DEC02F140C000000000000000000000000000000000000000000000000000000006171865D000000000000000000000000000000000000000000000000000000000000000200000000000000000000000032EB7902D4134BF98A28B963D26DE779AF92A21200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1245550AFE033DE3F9E7967582A7738A2DD077AA85EA5834FE1A189F61EDFB9CE12DE036EBD4C9CD227125281C37BFA52841B503AEDD004809DEE24F5B312074E000382016807FF06845A87F8D2831CBE0B9433CEB27B39D2BB7D2E61F7564D3DF293440204172A0FEEA0D7B2000000000000000000000000000000000000000000000000000000000000008900000000000000000000000053E72EFE3B3776C395D99603971F3776D9061449000000000000000000000000000000000000000000000000009536C7089100000000000000000000000000000000000000000000000000000000DCF70F0C297B000000000000000000000000000000000000000000000000009327767D6282F500000000000000000000000000000000000000000000000000000000617ABA210000000000000000000000000000000000000000000000000091B685470355F600000000000000000000000000000000000000000000000000000000617ABA2193793128E582FA1B4CDFA2E4406C5E2D768BAFB916DD3AFE228011FE3C3B4545480B12E395A8106486317EDC8BE584F6253E529C316A5898DBF48AD542F24B0B000381A807FF06845A87F8D2834C4B4094A906F338CB21815CBC4BC87ACE9E68C87EF8D8F1191053A8AA03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002B6DE8E50D6C4EF83B58D5B81631ADD03A5F3FFB79EECCF10E742EFAFA3D565628470C7B9A377508DC4C952BA1B0D218F4879DA9AE6042BD76943C1AE222C8B9116617146ADF184E91000381A707FF05845A87F8D2831069109430DF229CEFA463E991E29D42DB0BAE2E122B2AC780095EA7B30000000000000000000000007544FE3D184B6B55D6B36C3FCA1157EE0BA30287FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5B82CFBD7480E01361DCCDCC7D63A9F599D5FE7398D2C284B96F882548781CD59BDC8EA0AEFE4E34002111E8169B8D433C8CD08DCB8B930140CC3EA815AAEAB000381A907FF8203BA845A87F8D2831642E094FDE5D7B7596AF6AC5DF7C56D76E14518A9F578DF80822255DE000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002C54B97004F1A5FC8AFA4BA072E22F0B891BC804006551C5D2596738E646E5A8F6435FBBA498108A718039710C1003C9132E3A76E0B6763BD65456A8B1D676A270CB6882C010382012F07FF02845A87F8D2831DBB7E941B02DA8CB0D097EB8D57A175B88C7D8B47997506871387E2CD14285500F305D719000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000000000000000000000000000000000000158D9400000000000000000000000000000000000000000000000000000000001571FD800000000000000000000000000000000000000000000000000136EE2F2740E8700000000000000000000000051E0DCF9C00CBFB82C1E20220F48E1F5C12729100000000000000000000000000000000000000000000000000000000061718686CF280052BACCEF5F85AAC1A53C0ACFF06DE9C225D90CD121ABFAFC0C267E6F825DCE514BC6D78E724A8DDE25436B5A863536D96E7697A76B2617FC4104CAEA9F00038201A707FF26845A87F8D2832D1E74941B02DA8CB0D097EB8D57A175B88C7D8B4799750680DED9382A0000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000000000000000000000000000C84EB4A3195C43E750000000000000000000000000000000000000000000017EDAD9C0D9E0E0A4FB300000000000000000000000000000000000000000000000006C5F2CC78FF080500000000000000000000000095F8F46F5F2A7BBF62F832415B91B014B37A92980000000000000000000000000000000000000000000000000000000061718B0D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001CBC92551CDC3ED62EA6172A06BE686D056E3D13C5B7CED18B0D501C9EDA7BDB9B7EF401FAB72F5B69C1162EC62DED214828CE186CFB27F43F1BB5235F6541481829156F9DF109DAC6EF3BEB0175C0B4FF55705C93FA9C627C056CC8A1337218C65DDD1C775AAA98379F0F878CC10315CAC5E6A917BBCCD8D003A539EA1A099247000382016A07FF20845A87F8D2831CC7ED9433CEB27B39D2BB7D2E61F7564D3DF29344020417822C000CEEA0D7B20000000000000000000000000000000000000000000000000000000000000089000000000000000000000000EF94AF0495DDC90F0D81AD2487578E9C554C40E90000000000000000000000000000000000000000000000000028048C5EC000000000000000000000000000000000000000000000000000000000DCF70F0C297B0000000000000000000000000000000000000000000000000026D56CA0F52A5F00000000000000000000000000000000000000000000000000000000617ABA270000000000000000000000000000000000000000000000000025D36D238589DB00000000000000000000000000000000000000000000000000000000617ABA2734F4454F8E29189DBE54C89D388AB527D52E1ECC27BEC6D8B60937322EC38FFC51B8A45A9E5C24F686CF7D3407240F2B8E72F08780DF616E1A99D8D0C8714CD101036807FF80845A87F8D2830EB67E9482AF49447D8A07E3BD95BD0D56F35241523FBAB16510D0E30DB04AF719FABCFD2CE8C20CEE50E221219A347BDF4DE2D01E41F460221686BC46B47A4442D287B30E65671188D371286968EB9E716A2665C98578492CB78C3BE6B80103820EAB07FF1F845A87F8D2833DA2429411111112542D85B3EF69AE05771C2DCCFF4FAA26807C025200000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001800000000000000000000000004E352CF164E64ADCBAD318C3A1E222E9EBA4CE42000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000034851EA13BDE818B1EFE26D31377906B47C9BBE2000000000000000000000000D50735819DDDDEA6BDEFE7B258B5B88D21DDA93900000000000000000000000000000000000000000000001B1AE4D6E2EF500000000000000000000000000000000000000000000000000000000000069FC073390000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002A000000000000000000000000000000000000000000000000000000000000006E00000000000000000000000000000000000000000000000000000000000000A0080000000000000000000000034851EA13BDE818B1EFE26D31377906B47C9BBE20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000024BD6015B4000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064EB5625D9000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000E4B2DFC82977DD2DCE7E8D37895A6A8F50CBB4FBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000384B3AF37C000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000208000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000100000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002447F8FE7A000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000004000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E00000000000000000000000000000000000000000000000000000000000001C0800000000000000000000000E4B2DFC82977DD2DCE7E8D37895A6A8F50CBB4FB0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000084E67CE7060000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044CA19EBD9000000000000000000000000E4B2DFC82977DD2DCE7E8D37895A6A8F50CBB4FB0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002647F8FE7A000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E00000000000000000000000000000000000000000000000000000000000001E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A405971224000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004470BDB947000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000000000000000000000000000000000006B0E16CA20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F99000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000D50735819DDDDEA6BDEFE7B258B5B88D21DDA93900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E26B9977D7F079C08E8ADF445210682BF3A4BE3332091D788B7A24C40ACF6CED6C9B86C729241F31DDFDF0728E5510E22624A0CE4CA02FCB1D3796DA63ED3138EBE8EEF101038201E807FF8197845A87F8D28322ACA494E1B8800C33672A495AE2CBC882C14E7C9438166C809F330727000000000000000000000000C26EFA8199105D317AD00A2E90BC5EA445A3CF5F00000000000000000000000000000000000000000000000000000000000000380000000000000000000000002913E812CF0DCCA30FB28E6CAC3D2DCFF44976880000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110B6E2E0000000000000000000000000000000000000000000000000000000010B4296A00000000000000000000000000000000000000000000000000000000617182030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000ED4AAE06CF69B36AE000000000000000000000000000000000000000000000000000000006172D12B695DDECC61D2C65E25BD70783B27F42EF723DFF4A3F3531F3887B524DACCEB6E4BCD6040C41B6ECB829B091BBB1DDECE2E4C6990AB59DF7F3A9AFE857B0DEB3D0003818707FF62845A87F8D28321565E94226CB17A52709034E2EC6ABE0D2F0A9EBCEC1059803CA58A010000EE00011300000000000000025054D62C000000000000000000EA2808001C8ECBD85E488352C79EB71DD34657EFDC70B990707770EADB18B24C3E2D0742CE67D97ACC3DDE847655AF553051165F24A1C64DC5136A15CD69F127A89C3D6B4201036807FF01845A87F8D2830EB67E9482AF49447D8A07E3BD95BD0D56F35241523FBAB16510D0E30DB0B846DE69F728983D98C38A74240AA512F1CA36961FC3777B857C6B22FF14FD09239ADB924A7DBB0F99F18EBCE63174D526CFEC5509147EAEF1C9B18DA44F4E3F010381A707FF25845A87F8D28310689894FEA7A6A0B346362BF88A9E4A88416B77A57D6C2A80095EA7B30000000000000000000000007544FE3D184B6B55D6B36C3FCA1157EE0BA30287FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEAF8822AB6A59E022ECA1AD26AA07E29069FD0D2854F77603762B2B48F19006F19D99DD76505ED9577142A3479B3C550A352B574906A1F08E06111D22BEB39A5000381A707FF33845A87F8D28317E569942A8104C4E5E0CCACCD84E3AB0F463FBAA749898180A9059CBB00000000000000000000000035AD622C650CF1FF39584A82D9152DF164A99C92000000000000000000000000000000000000000000000000000021EE601864358413C691FAAFE05AF856C88020B104046EC29FAE13AAFD4314C553AA6F6D5D403E3C16A36DEFAE6B020D8041243C41FA0E6C169E11ADF7C9C45A2CD4586C3577000381E707FF06845A87F8D2833443BA947544FE3D184B6B55D6B36C3FCA1157EE0BA302878029ED286200000000000000000000000030DF229CEFA463E991E29D42DB0BAE2E122B2AC70000000000000000000000000000000000000000000005C1B25118AA5F19F14600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000653D00CE343F5CBD561F3740AABD601E062A55B70B20E82D597868D10B4EA3AEAA4EF6BDD1149AB85163E5097FDA34A56555591D371EA1263F137D8E97B006B290EC5EFB2000382010707FF26845A87F8D2832C9CD1947544FE3D184B6B55D6B36C3FCA1157EE0BA3028780A318517900000000000000000000000030DF229CEFA463E991E29D42DB0BAE2E122B2AC7000000000000000000000000000000000000000000000F1E56536C7142B8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EF67A10C257DD31583B36BBB3710032536D7FDF19B0796B80644F73E255934405BADB1181FC726FB36E3865CC519424D294E5622CA5F01A20FBEE20DEAADB00FA717F337714F83552D0000381A707FF11845A87F8D28313A978943E6648C5A70A150A88BCE65F4AD4D506FE15D2AF80095EA7B30000000000000000000000001B02DA8CB0D097EB8D57A175B88C7D8B47997506FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6A76EAFFE8130C9E0A8B5149C95936A1D21AA1FDFEB3F5B497E34235C76F1817BB99154C42E1133107E563F808EC26954CAB5EC68AC2CA96A7D13098C4A12510003818807FF80845A87F8D2830B9BC99400000000000000000000000000000000000000641B1025E16063000000000000000000000000FB63CF993F2712FEBCF47CA8292C4541F23AEDC24242232A77D10266FD2B338FD9D9B5BB9A59A702B4E0900E2131DF2B0A0926AC47CAD5436B34AF74D88203269B38214EE087A187B7D5C404A7BEA0712C5E6A51010382016807FF07845A87F8D2831AB92094E592427A0AECE92DE3EDEE1F18E0157C058615640511414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A00000000000000000000000000000000000000000000000000000000000027100000000000000000000000005F43CD11F9C147A2320FDD900EF35B68A0A39A1200000000000000000000000000000000000000000000000000000000617180AA00000000000000000000000000000000000000000000000006F05B59D3B200000000000000000000000000000000000000000000000000046E08D2A0DC874B460000000000000000000000000000000000000000000000000000000000000000144508EBF132DED56FD655703B31607651665259E61277FC274685AC3D5CB7BC7BF93A582BB358BDB836F9272216B9E97926557069ACB36D862EF37EC960DCFA000382016707FF2E845A87F8D2831AA336941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE5000000000000000000000000000000000000000000006092A0E2A4F28D5000000000000000000000000000000000000000000000000000001B1BB505E04CD24600000000000000000000000000000000000000000000000000000000000000A000000000000000000000000049BAD8DF161888AB67B8A66EBFE8574F197A5AA8000000000000000000000000000000000000000000000000000000006171868600000000000000000000000000000000000000000000000000000000000000020000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB12D963B281BD8D6FD7EEF155C1C2CAB2ED803B3F1BC291C7BD58F6583FDD4C6E31CF4903D88EFEE6FD650548F559184534BB5AF817D0CB885316EB5BD9785FA1C000381A907FF82059A845A87F8D28312E7A09472C4E7AA6C743DA4E690FA7FA66904BC3F2C9C0480822255DE000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002540BE400E0187ABB547936C6AD9C09B153484CD3089012614F3BFD4F8CEA3D177A9C48CB0D02DF06370E70C9210DABF72C8065F636F76C086A0FB1D7BDD622712C3402F7010382014707FF27845A87F8D2834C4B4094A906F338CB21815CBC4BC87ACE9E68C87EF8D8F18030B70002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000138AE94470BC3216F74259C5D6BD04930D5135CCC71226F9A276A01B44B6A7016544B9E7D93CA97F0D8541B5EAD2C7E47F918344108AF5ACA9B5EDDBD34FC46BD000381A707FF27845A87F8D28310593C9430DF229CEFA463E991E29D42DB0BAE2E122B2AC780095EA7B3000000000000000000000000839DE324A1AB773F76A53900D70AC1B913D2B387FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE96B5B2B6FC9BEB0A3EDEE5F682378E83ACAF21B56BDE7FDDDDB65363BB6B01321057160633E44D89A183D1C1E322B848BBAD38240D25A38AA36441DBC059424010381CA07FF826F478506FC23AC00832DC6C09473FE72C9CAA0FAF0E488570D5898984783E728DF801D4E37400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000067340000700C003EEBDA03CF0578A9C9D56AB13E95EBC45977773D0F6E9C44C5582F610A994FE5D035907A8EBA814DB567C384D5F5C5BDC5A2C0754EE1FB463C93E551B7F8A727B395D8CF65AD84010382036707FF06845A87F8D2831B443994BA12222222228D8BA445958A75A0704D566BF2C8808BDB391364541216BAFFFEEC8EA535BB71FBC927831D0595000100000000000000000002000000000000000000000000DF8B7DBE87A5332B5ADC7B61E8DC273302205500000000000000000000000000DF8B7DBE87A5332B5ADC7B61E8DC2733022055000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC4FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000047148A0A0AA76FC0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1A2BC2EC50000000000000000000000000000000000000000000000000000000000000000000009235F091BDD589FA75C741573E740A11AA4C05EBD6D77A46C9A446ED32E66391A4C17D5059D254B69FE5EFC4EE506B84BA764D204F9F791FAC2C3344BB9454D010382016907FF82109A8477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480DB3E2198000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718B3600000000000000000000000000000000000000000000000086BD4C0F3C448000000000000000000000000000000000000000000000000000000000097FDE98000000000000000000000000000000000000000000000000000000000000000000FF3E766512CA33B163509CFD24E88D11C8B8EBA981A4B284C999BFE0812D4FDD5FBA8F1AB3BFB49A378DDE8210052E11A5F6279BBDFF325A20D79CB489630245000382010A07FF83016D4D8443E5FA9E83124F809457469550B9A42D2FD964E67A9DD1DE3D9169B2918091C88C4C00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000061717FD9000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DF8B23C2F7478D000046B3C2C10B1BFAAB1DD703112FA6E224792AF5F3A898F8DDE2296CBFDD7C4A3D250324968800836C11EBACD5D26E7865C203AB750C2A1FEAF4914C2562C96D5A000382010707FF41845A87F8D2831542639499CF05461DD5F94761D4FAE6A2ABDA47A93451F58031C1ABDC0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ACEDEE0C6982873C1FBF036AC6B1DF37D0072B2D00000000000000000000000000000000000000000000000000000000000000020000000000000000000000004E3985931AA4CE680A506F5B7302F670EC97428F0000000000000000000000000CF0EC28869367A4FE6B24A487991FAFF9788BF138E57B7EB13BB759E0B867C6326F166D3EC44F451BAF56AB8ADAE4BA29BC5A826720D361FD10F2EDA6D527EF7F9E508D81CC226EFFE60B8FB3C9FAA9DB74D58901038203C707FF6C845A87F8D2831BC713943B6067D4CAA8A14C63FDBE6318F27A0BBC9F9237807617B38900000000000000000000000010010078A54396F62C96DF8532DC2B4847D47ED3000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000310C9799DA1071905300000000000000000000000000000000000000000000000000000000723FCCFE000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001A0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000006171846600000000000000000000000000000000000000000000000000000000000000020000000000000000000000008AB2D334CE64B50BE9AB04184F7CCBA2A6BB639100000000000000000000000017EBC315760BB47384224A5F3BF829222FBD3AA7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000065E17C52128396443D4A9A61EACF0970F05F8A20000000000000000000000000905DFCD5649217C42684F23958568E533C711AA3000000000000000000000000000000000000000000000000000000000000000300000000000000000000000065E17C52128396443D4A9A61EACF0970F05F8A20000000000000000000000000905DFCD5649217C42684F23958568E533C711AA30000000000000000000000000B079BC0215C6D227F80D6C08366C2A29D4EC13E0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000BC88D3448199EAEC6A488860839CB1BF8CDAE5DB379FE52712306B948BDE4BEC77E956A3C3C5084001FE20D6F64AEC25E1EDB7B8BFBAB8D734B47DD3A88F96D6010382016F07FF80845A87F8D2831AF8FC94E592427A0AECE92DE3EDEE1F18E0157C05861564870A4D88AE36370D02414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000DA10009CBD5D07DD0CECC66161FC93D7C9000DA10000000000000000000000000000000000000000000000000000000000000BB8000000000000000000000000152EE8305721181984B577EA9E5704BA5805169A00000000000000000000000000000000000000000000000000000000617180AA000000000000000000000000000000000000000000000000040649640D2D8114000000000000000000000000000000000000000000000040BEB19AE5CF216CD30000000000000000000000000000000000000000000000000000000000000000EE6E161C474D772F59E33283CBECB9620257631873798EFF87AE1AFB72C6879421EA0E948B615CD87643164CEDCD472B489DEAA9BCDE179584A163AEAF983D850003818707FF1F845A87F8D2830BB8A99482AF49447D8A07E3BD95BD0D56F35241523FBAB1802E1A7D4D0000000000000000000000000000000000000000000000000018DE76816D8000E64656912B260A5CA0D8BD4E2E73132341BB4F271E95CBA13D3F66ABC87801503B440F043A34B1BE67A4F988AA338FD2586CB55478988BAA1220ADB46EA34E0D010382016807FF8182845A87F8D2831ABAEE941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE5000000000000000000000000000000000000000000003D71A6363E67CACA79A7000000000000000000000000000000000000000000000000113D33153D7E4F9C00000000000000000000000000000000000000000000000000000000000000A000000000000000000000000080AF73FEEF1B9D0F2EF230A548D752E7DC984646000000000000000000000000000000000000000000000000000000006171868600000000000000000000000000000000000000000000000000000000000000020000000000000000000000003E6648C5A70A150A88BCE65F4AD4D506FE15D2AF00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1F56432A99288228985C45F612D43859653897F4C1C38E12DB540328C4EEEFAEB5B157F3758EF00C9F4140FB1A218E5799CEF65F801D2A33ED98180C930F4E6F6010381A707FF02845A87F8D2831059409430DF229CEFA463E991E29D42DB0BAE2E122B2AC780095EA7B3000000000000000000000000839DE324A1AB773F76A53900D70AC1B913D2B387FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88DA75549789D24CDFB83508414E3E95D605034B4FE31D05628C0E60ADEE7BE0FF80CA06797571EE29D65A676CD4CEC7A3F1029584568D2ACB40EC7CB59344A000382028707FF04843B9ACA008325C5FF94C36442B4A4522E871399CD717ABDD847AB11FE8880AC9650D8000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000A40C49CCBE00000000000000000000000000000000000000000000000000000000000026C900000000000000000000000000000000000000000000000000000C2BDA35134E0000000000000000000000000000000000000000000000000008333DA855DDE1000000000000000000000000000000000000000000000000000000000B2DFF4700000000000000000000000000000000000000000000000000000000617180AA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084FC6F786500000000000000000000000000000000000000000000000000000000000026C90000000000000000000000009D5FBDA32AAD9F83B307499854674E11C4B5F63800000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000CAC1BAAB3522D4C4E8E026809A47E2EC9A1CDE5B1FAC870981D10793897C4A021366CA414C2ED94AA933915E82F48799F829AE652856436242E239CFCF3FF2000381A707FF28845A87F8D28319F50694839DE324A1AB773F76A53900D70AC1B913D2B38780E2BBB1580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F1D1641F1B2E7C5B219C0933CF35433A1CA4889B8FD8028481B622026764DE04307D78C76C404E3FEDA2EFC9AC6246C3F41D972FDF2CD7666B8D750CD544017247E2733D796975BF59B0103820DCB07FF20845A87F8D283457EA59411111112542D85B3EF69AE05771C2DCCFF4FAA26807C025200000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001800000000000000000000000004E352CF164E64ADCBAD318C3A1E222E9EBA4CE42000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E000000000000000000000000D50735819DDDDEA6BDEFE7B258B5B88D21DDA93900000000000000000000000000000000000000000000001B1AE4D6E2EF5000000000000000000000000000000000000000000000000000000000000693467FD10000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BC00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000092080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064EB5625D90000000000000000000000004E352CF164E64ADCBAD318C3A1E222E9EBA4CE42000000000000000000000000BA12222222228D8BA445958A75A0704D566BF2C800000000000000000000000000000000000000000000001B1AE4D6E2EF50000000000000000000000000000000000000000000000000000000000000800000000000000000000000BA12222222228D8BA445958A75A0704D566BF2C800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001E452BBBE2900000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A31BB36C5164B165F9C36955EA4CCBAB42B3B28E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000006172D163B5B77F1AD2B520DF01612399258E7787AF63025D00020000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004E352CF164E64ADCBAD318C3A1E222E9EBA4CE4200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000001B1AE4D6E2EF50000000000000000000000000000000000000000000000000000000000000000000C0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000164B3AF37C00000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000000400000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000000000010000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000242E1A7D4D00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001E4B3AF37C000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000044000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE0000000000000000000000000000000100000000000000000000000000000001800000000000000000000000960EA3E3C7FB317332D990873D354E18D764559000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A4394747C5000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F99000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000D50735819DDDDEA6BDEFE7B258B5B88D21DDA93900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E26B997790DC8D845EF53593B072A4397A720DBCC247245F8BDEB3269AEB3A1E8FA98A1F59355DF467358C65C0AD846D7CF7FD028F05368CEBD7FFD973E085CEE5260BD400038202A707FF0E845A87F8D2831A65D794E592427A0AECE92DE3EDEE1F18E0157C0586156480AC9650D800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000104414BF389000000000000000000000000FA7F8980B0F1E64A2062791CC3B0871572F1F7F000000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000BB800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061718081000000000000000000000000000000000000000000000000BF3C64FD8CE200000000000000000000000000000000000000000000000000000138388594041F4D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C0000000000000000000000000000000000000000000000000138388594041F4D0000000000000000000000006BE232616B4862F5DBC14FD19BB704D7596CB1FF00000000000000000000000000000000000000000000000000000000271AE69C572F734BCBD58D59A5F0365DBF00EEF11CEE418EA21435097E646F122152BAEFD09A83F170300730CBD6EDDC6BB446CB2DC3E5A8BAB39F19F24E40F6000381A907FF82064B8477359400834C4B409424C4F5E7A271831264BB4C1458BE96007C25FFB8802CBE4E95000000000000000000000000000000000000000000000545E77EE3B577800000000000000000000000000000000000000000000000000000000000000000000163B8BF77F3DC89A0BF180628AA1094B9DBCEA348D98C86BC1D2058DF7F37244F21F8E703F35362AAD1762F24AFCAE0F1F7B01CE310E0398421BBFC0C65AEA8A5010382010907FF8209DE8459682F008389544094FDFE6CFB409F29BA7A23E7ADDFD5458434869523801E5C714E000000000000000000000000000000000000000000000000000000006171811600000000000000000000000000000000000000000000000000071AFD498D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000526F24C41A8A8E808403B5110BE48EB225BFEC36658095246BF3D4C7DAC079B73FCC81D05371906015C071D7C068544AD365AC870DAF869F010396E863A6B4832E1B3F5EE5166AD300038201E907FF8208BF847D2B7500834C4B40942ED6BC5830AD51A0A8FFEDA475DC64E3C355314480369460150000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013A000000000000DF988FB9F431E000010103030060C24F7D8E51A64DC1238880BD00BB961D54CBEB2982AF49447D8A07E3BD95BD0D56F35241523FBAB1FA7F8980B0F1E64A2062791CC3B0871572F1F7F000000000000000000000000000000000000000000C7ADB64A66471000000000000000BB80300602DFBBC8C9405C70CA0F81944332841663D2333B1FA7F8980B0F1E64A2062791CC3B0871572F1F7F0FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000005820187203C48C000000000BB8030060C31E54C7A869B9FCBECC14363CF510D1C41FA443FF970A61A04B1CA14834A43F5DE4533EBDDB5CC882AF49447D8A07E3BD95BD0D56F35241523FBAB101000000000000000000000000000000000000000000043636E6B97128C00000000001F4000000000000BD6BD91D3BC012C020F78B6374B70CDC3972A5DA8CCAE90D95D4046E48E682E222CBC4488941AE26EC4011E20BDED121AEDC070F1E5D59DE89CCB7CEC50B778A000381A707FF08845A87F8D2834C4B4094FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A80095EA7B3000000000000000000000000908C4D94D34924765F1EDC22A1DD098397C59DD4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF192264F53485C63B54729701C5DE6D836D3E0D39836C7F33331CBD3675A75F566DB4D3187D0C635A6C544C7E4048B75352D60439CAF904EF0C61EE6CE49D7B3001036607FF05845A87F8D2830B443294E77672011DEA3D78C49A4D1DAC38DA7E93E812A28201A10F86DB846477E532D9BEAEC2545D7F667A4F586C32AEDED5004F0D0538B6016F5862D7609D2863074376FB8269EAB01E5DACED6F631D3A3484542EB30AC2961AA4000382016707FF22845A87F8D2831A8EE2941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE500000000000000000000000000000000000000000000000000955FEA907051A80000000000000000000000000000000000000000000000000030DE1F4C4FA92600000000000000000000000000000000000000000000000000000000000000A000000000000000000000000049D56C2020CAAE817C3B493B00E5C6DEC02F140C000000000000000000000000000000000000000000000000000000006171868600000000000000000000000000000000000000000000000000000000000000020000000000000000000000006C2C06790B3E3E3C38E12EE22F8183B37A13EE5500000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1B189A853938550727AED7E1040A8717C1E658C3F4AE08A548B1037F0DA3E9AEB6B1AEFF33796C67140A02FE8B19090B323436CE602CC6B014915956B76D3AF4B010381A707FF03845A87F8D28313A84194FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980095EA7B3000000000000000000000000E592427A0AECE92DE3EDEE1F18E0157C05861564FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD18481ACC4B090706FF27BCB445FB93A75AB2C4D8E946F192C0A6DD94E73EFDE5EFF6B046611325E590BB024C369D2A4CDE0D00AE03116112D93AEED07C990C6010382016907FF82109B8477359400831E848094E592427A0AECE92DE3EDEE1F18E0157C0586156480DB3E2198000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000E9EE83812FA9EFF257AB4F5F4BBD222A1D32F1910000000000000000000000000000000000000000000000000000000061718B7400000000000000000000000000000000000000000000000086AF1614A92A8000000000000000000000000000000000000000000000000000000000097FDE98000000000000000000000000000000000000000000000000000000000000000000C3A31BC8234F64C93B59F1A81BF6CD5BF84759D2389BFE4AE6532ADBAB4D93F368146CDF0E6663A8E39941D6D9E10FAAB966081A78B2ACD2741CA1FF0ACB45860103818807FF8183845A87F8D2830BCC769482AF49447D8A07E3BD95BD0D56F35241523FBAB1802E1A7D4D0000000000000000000000000000000000000000000000001161C837389C4CE3A917CE105F26AB7E4EE397E3ADFC008606764012D6204E0777E17CD7ACC2B4376E50DE1F67380F3C611FDDAC9AAA9117B4EEEFD3730C928D8BC1AC7355E9B95B00, lengths=[170, 0, 172, 0, 269, 0, 172, 0, 395, 0, 299, 0, 139, 0, 526, 0, 427, 0, 396, 0, 102, 0, 363, 0, 105, 0, 102, 0, 429, 0, 364, 0, 747, 0, 1073, 0, 205, 0, 365, 0, 334, 0, 429, 0, 363, 0, 364, 0, 299, 0, 875, 0, 363, 0, 628, 0, 365, 0, 138, 0, 364, 0, 170, 0, 105, 0, 429, 0, 365, 0, 1003, 0, 363, 0, 170, 0, 138, 0, 106, 0, 555, 0, 471, 0, 365, 0, 170, 0, 205, 0, 365, 0, 429, 0, 366, 0, 202, 0, 270, 0, 138, 0, 365, 0, 372, 0, 363, 0, 363, 0, 267, 0, 372, 0, 365, 0, 875, 0, 105, 0, 140, 0, 301, 0, 203, 0, 170, 0, 683, 0, 170, 0, 459, 0, 170, 0, 1003, 0, 332, 0, 750, 0, 105, 0, 267, 0, 202, 0, 459, 0, 170, 0, 170, 0, 138, 0, 331, 0, 302, 0, 1038, 0, 205, 0, 460, 0, 691, 0, 441, 0, 2994, 0, 138, 0, 365, 0, 102, 0, 102, 0, 138, 0, 363, 0, 138, 0, 750, 0, 170, 0, 363, 0, 395, 0, 172, 0, 1133, 0, 171, 0, 170, 0, 170, 0, 170, 0, 875, 0, 307, 0, 170, 0, 202, 0, 459, 0, 140, 0, 1655, 0, 333, 0, 172, 0, 875, 0, 334, 0, 171, 0, 140, 0, 270, 0, 363, 0, 3535, 0, 696, 0, 171, 138, 0, 363, 0, 724, 0, 875, 0, 363, 0, 395, 0, 107, 0, 363, 0, 691, 0, 202, 0, 683, 0, 1006, 0, 105, 0, 105, 0, 332, 0, 363, 0, 267, 0, 170, 0, 396, 0, 875, 0, 363, 0, 364, 0, 171, 0, 170, 0, 172, 0, 307, 0, 427, 0, 366, 0, 106, 0, 3759, 0, 492, 0, 138, 0, 106, 0, 170, 0, 170, 0, 234, 0, 267, 0, 170, 0, 139, 0, 364, 0, 363, 0, 172, 0, 331, 0, 170, 0, 205, 0, 875, 0, 365, 0, 270, 0, 267, 0, 971, 0, 371, 0, 138, 0, 364, 0, 170, 0, 651, 0, 170, 0, 3535, 0, 683, 0, 172, 0, 269, 0, 493, 0, 170, 0, 104, 0, 363, 0, 170, 0, 365, 0, 139, 0], sectionsMetadata=[0, 13461658, 1634827907, 187870, 91016067255575704435722146162603075390110871418050664611102976869258423087232, 30, 13461662, 1634827940, 187870, 0, 36, 13461666, 1634827990, 187870, 0, 52, 13461670, 1634828027, 187870, 0, 66, 13461677, 1634828067, 187871, 34392722399502959987432898239862721731876208181439426508553689132956883517527, 85, 13461682, 1634828117, 187871, 0, 94, 13461686, 1634828158, 187871, 0, 12, 13461690, 1634828220, 187871, 0], afterAcc=77FEDFC233DA79E0C8FEA4F15C68D7DDD4027879DA1D9BE020CEAD9C27AD41AF, gasRefunder=0x284c1875694058b213866F5F2aD015b5a4B9438b )
    • TransparentUpgradeableProxy.STATICCALL( )
      • Bridge.DELEGATECALL( )
      • TransparentUpgradeableProxy.d9dd67ab( )
        • Bridge.inboxAccs( 187869 ) => ( C93944BCC1F3005DE398BD58EB8C2E101809C061DB39D606C78DABE2A606B080 )
        • TransparentUpgradeableProxy.STATICCALL( )
          • Bridge.DELEGATECALL( )
          • TransparentUpgradeableProxy.d9dd67ab( )
            • Bridge.inboxAccs( 187870 ) => ( 4C09974EA197427D28409B15D17852162A55EEBB0D641E1B9686125F48928057 )
            • GasRefunder.onGasSpent( refundee=0xa4b10ac61E79Ea1e150DF70B8dda53391928fD14, gasUsed=313352, calldataSize=92260 ) => ( success=True )
              • ETH 0.090769086524561872 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);
                            }
                        }
                    }
                }