Transaction Hash:
Block:
14756364 at May-11-2022 06:10:40 PM +UTC
Transaction Fee:
0.18023821311264832 ETH
$340.73
Gas Used:
1,241,704 Gas / 145.15392808 Gwei
Emitted Events:
20 |
TransparentUpgradeableProxy.0x10e0571aafaf282151fd5b0215b5495521c549509cb0de3a3f8310bd2e344682( 0x10e0571aafaf282151fd5b0215b5495521c549509cb0de3a3f8310bd2e344682, 0x000000000000000000000000000000000000000000000000000000000174c910, 0xce0288b999a57971b8c72cf76004a7fe10f655dd41f0d9977170e7d5d33aaadf, 000000000000000000000000000000000000000000000000000000000174ca56, 264373fad115e6461feaa72c59343d8fc8e6970d92d330276052fadd8add09c4, 000000000000000000000000000000000000000000000000000000000000f8da )
|
21 |
GasRefunder.RefundedGasCosts( refundee=[Sender] 0xa4b10ac61e79ea1e150df70b8dda53391928fd14, contractAddress=[Receiver] TransparentUpgradeableProxy, success=True, gas=1504596, gasPrice=145153928080, amountPaid=182029444346663280 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x284c1875...5a4B9438b | 117.356597424258978914 Eth | 117.174567979912315634 Eth | 0.18202944434666328 | ||
0x4c6f947A...C874F95Ef | (Arbitrum: Old Sequencer Inbox) | ||||
0x7F101fE4...353f2B90c
Miner
| (Flexpool.io) | 6,171.187421252079313086 Eth | 6,171.18887813235742327 Eth | 0.001456880278110184 | |
0xa4b10ac6...91928fD14 | (Arbitrum: Sequencer) |
2.00504058354499832 Eth
Nonce: 60601
|
2.00683181477901328 Eth
Nonce: 60602
| 0.00179123123401496 |
Execution Trace
TransparentUpgradeableProxy.8a2df18d( )
SequencerInbox.addSequencerL2BatchFromOriginWithGasRefunder( transactions=0x0382040A07FF82AC5B85E8D4A51000836ACFC094EFC5061B7A8AEF31F789F1BA5B3B8256674F2B7180C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000E193445CE0BAE19053668642A3CB19770000B5800107050102090306080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000001FC999C8000000000000000000000000000000000000000000000000000000001FF69626000000000000000000000000000000000000000000000000000000001FF696260000000000000000000000000000000000000000000000000000000020038F5E0000000000000000000000000000000000000000000000000000000020061EE700000000000000000000000000000000000000000000000000000000201CE7AD000000000000000000000000000000000000000000000000000000002034ACFF000000000000000000000000000000000000000000000000000000002034ACFF00000000000000000000000000000000000000000000000000000000203F014000000000000000000000000000000000000000000000000000000000205B7C2E0000000000000000000000000000000000000000000000000000000000000004644C83D073952840276047D3AF449D00072974FF3659CFF0E546E688B08A41A64CE9E4DA77BF213C02A7064E9C54DA5D1FD34EF6CCDBB67CBB7A014867B3691AC8CB59C7A12A4B417478D15AECAE09296024CDF2D3C06518CAAF46F2977ABF0E275EBEC73461078FF9726608A1A4D8F8E8664DA887B464CB9693C68E92E10EA80000000000000000000000000000000000000000000000000000000000000004797327D52C3CBC8A53EC3E9D5823D499B601149D2608C41785A61890B4A7AA913ED5937FD4DA35BD308FA48BD118777644DB25B929B914C7C1D3E2F338717BA532E8B5BD56F9EC416EF4D77B1A8507A055C2E779597E66A2E83CC4557ABD7CEC7A1B09EB5FAFE8375FE97E8682548D9F0B74E155E19218232439DEFC3FE5BBB2C7BBE461B140DF491C863EE3DF809375640E680E8A11FDF202C012629AB5B2391D0A0B40A837D4CE0FD9E5490DCCB4DD7971964C2797F9F33950C7117E5D72150003818807FF81C7844E6D78108307CF5E946A0F4AFB31E90C378FA2AAA40371A652578F339B80A694FC3A00000000000000000000000000000000000000000000000000000016C6C32C787E55478DDFAC144FE8EE0790C8F1313B61967B8467806D2443A3EF695B64CEFD3C1AB589874EA6EC41D5BDBFCF1ACCD4308090CE0CB09CC7AE6D5D9081934AC30103818907FF820107844E6D7810830831F994DFB034CD2789B9F85E57D25C69E161EA0BDC8F538095A2251F00000000000000000000000052079CB2859D58444B368A2506E9EC0B2FF7E7773C2B06EDC3695F447C66350DA56F81717E3FE98DC76B6C9F017922B55F7C7924392EF63B6067CF9FBEA47AA39AACFAB19045F37E332939AEF2F5C8232B9C3019000382016707FF07844E6D7810830FBDBA941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE5000000000000000000000000000000000000000000000000137295CE4ACAEC360000000000000000000000000000000000000000000000000FD0B5ABC39DE19E00000000000000000000000000000000000000000000000000000000000000A00000000000000000000000003B378222FA3E3DCE3B4BFE07794CEE6FCB724AA000000000000000000000000000000000000000000000000000000000627BEB7800000000000000000000000000000000000000000000000000000000000000020000000000000000000000008D9BA570D6CB60C7E3E0F31343EFE75AB8E65FB100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB17B38AECEA610265E43E5DF9762F8FC9F068869B27C4230025C3285DCBB22358F06157456596EC396D44C6B9012507375DB2E652F7F41A88B10309478E0592085010382040A07FF82AFD385E8D4A51000836ACFC0944258E5D50D737CBBEA347F0115AD166E234902D780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000066A780E93CB5C9F39687E1108B10DF910001F7BF0202040305000801060709000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000426DB68000000000000000000000000000000000000000000000000000000000426DB68000000000000000000000000000000000000000000000000000000000426E07C000000000000000000000000000000000000000000000000000000000426F148000000000000000000000000000000000000000000000000000000000426F986000000000000000000000000000000000000000000000000000000000426F9860000000000000000000000000000000000000000000000000000000004280E700000000000000000000000000000000000000000000000000000000004280E700000000000000000000000000000000000000000000000000000000004280E700000000000000000000000000000000000000000000000000000000004280E70000000000000000000000000000000000000000000000000000000000000000459CA7D19D1BCC1F942B2B232295BAD7C2DFCFBADFD90BF7337DF7DEBFA59C3741CB1144DFBD079C73BA161D01E51F12DACD51C035EBE3C9885D1BFBF9DC99F7F0BF1A9472036BAE4534A5D5936E998EFF7D1E1868799DA904A7E6A6F629DCA02F4A8A2A21F5C3F7412F017CAAA9D31DA6110C20101300C342230953755AA30C20000000000000000000000000000000000000000000000000000000000000004225B1F9FA8D672BE992F9BF618F25848CF824372707E9A04D0D944476C77DCEC30028A5A40400F9E7D35114AE6FBEAC26B1BEBEB33FAD63DF13C4534EC6AAB5B7E2236F93A60F7F77D75ACE316D2944B459CE2A654AAF47E3D322EEF1423F7F800188D94DBFCBFB83E6D1569EFEEF855260B1BCFD39BA726D99EF42A5F4F07C8C0A5734859EA2EDDDB2C388AC37EE2EF61815A2EB839CD995F52DE434F66A4EA6EF9B98642373A61878C54F3F78355A72E8D9BFE29E735F8CD8386B251206FCC01036D07FF82728A844E6D7810830F4240948162BCA53B1CEC1DFBF224083A1F039B80A6D568871CF378EA46505D000A6B521C9BF993EF009F5B8C04E28ED4150682E2321C72FAE01A8E3077B38DC50877D5D4C63230B80521892DFBA486AE5DD602C5BBE64EC4D56549108605C68E010381E707FF5E844E6D78108309789B94DA3CAD5E4F40062CECA6C1B979766BC0BAED8E3380F93309D1000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000006F4400000000000000000000000000000000000000000000000000000000000045E729A67F4236F4EAC1C3F731E9FF037D70D2BA9F06355E60047088A471E798FFBA34307EEF9A827A6A7538233E5F35FDEB823FD358D5FB290C01AAC9D7E94A73DF010382018907FF820910844E6D78108311AA5D941B02DA8CB0D097EB8D57A175B88C7D8B479975068038ED173900000000000000000000000000000000000000000000008A12B9BD6A67EC00000000000000000000000000000000000000000000000000000000000079185AF100000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000734740C70DB02F5710207F1D12DF47C71066520600000000000000000000000000000000000000000000000000000000627BEB780000000000000000000000000000000000000000000000000000000000000003000000000000000000000000539BDE0D7DBD336B79148AA742883198BBF6034200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8E19E8EFACEEA3F944BC49F48FC4DBFED5C5C7F7AD7045AF9DC4DAB0B79B1BDDE3E19DB138492B5DB6FB62D1E7D49D9217E0DEF5E16F1F9170E1319AE610181EE000382040A07FF82029685E8D4A51000836ACFC094A303A72D334E589122454E8E849E147BAD309E7380C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000007E0618996C2EB5A05B0D4853FBF6CE76000008E80104020007030901080605000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000007D1CCE77000000000000000000000000000000000000000000000000000000007D440A51000000000000000000000000000000000000000000000000000000007D8C4622000000000000000000000000000000000000000000000000000000007D8C4622000000000000000000000000000000000000000000000000000000007D8C4622000000000000000000000000000000000000000000000000000000007D8C4622000000000000000000000000000000000000000000000000000000007DE66F97000000000000000000000000000000000000000000000000000000007DE66F97000000000000000000000000000000000000000000000000000000007DF1D240000000000000000000000000000000000000000000000000000000007F6F4A800000000000000000000000000000000000000000000000000000000000000004EE2F764F6458831114C4987D4A79E5FEFF18791DFCD1B053983FA7AD1374DE51E6882CB77DA0EDBE4FFD8363752D57D14A5E9B15A16E2E996B3A0E5C13D347FE1E9A04948C58EB6BE24F8CDDC5C908B958F6D2F06137509BA6AF997306B00C0D9EB5FF815BF03AC78ABF66A9E0FA96B10D00E887D4C26B53AA0082C97E2860C200000000000000000000000000000000000000000000000000000000000000045A6AE435F621023A842EE7424D8C0D68E4000AFF1FA61C0F844C390F2B0C903A7727BCF97E393DCE691862BEA915340E5E56276BD3D371190A96915E57753C4A4E38C16DBA2EC3EBB97556AAC7656AEE516F919C820BD2104E119970B953694E1AF811C22AA614F170E8160247F9671B196FE34B0D4B24A27456068900DEBBC942A66A869667ABF675CFC1F7F750C682022D88A242B5BC499C0565275A1EF54644D0625BFABF624EC7538F6D6427BA5BD148CEA3FE996A0BA9BAB2A901DDB462000382010A07FF82313D85174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80D01FD32F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE5ECEC3117C0D3D6578AF3EC5FBD90BDD732C56E25426E35A396337FEBE84F62FBEC07BA19E011EF2361466FA634A7525ED6430894F90469C8A3D8A2FFA726593347010382020A07FF8201DA844E6D781083193F8D9409F77E8A13DE9A35A7231028187E9FD5DB8A2ACB670EB142A4B00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000002386F26FC100000000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C8D36B2AA3C5BAC5EA6100000000000000000000000000000002F2A2543B76A4166549F7AAB2E75BEF0AEFC5B0F0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000005E4F168772F7728FEEDC5400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110D9316EC0000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB137ED0465281252D4A1DED71FEE0D46996DDE7124CBCFF3CFAC9F62DA292E511640BAC9BFB6BEB86FACCA50B303848BEDD4C16C5F49422E1324D57D484F458458000381E707FF0A844E6D7810830D70C5947F90122BF0700F9E7E1F688FE926940E8839F353803DF02124000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000114592DAC00000000000000000000000000000000000000000000000000000001115439D88B9E3830DD52FC296F00747566313F04F8E95AFBFDD79D8816850CAC61CD5F0628C17D1DC11A1963FA205CE8610CB4B25C061C7D98E4D2C6594A2BAD61A4FB36000382086907FF82031A844E6D78108396DE9B94737EAF14061FE68F04FF4CA8205ACF538555FCC88070E419450000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003E00000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002DE8000000000000000000000000000000000000000000000000000000000000038B0000000000000000000000000000000000000000000000000000000000000394000000000000000000000000000000000000000000000000000000000000057900000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000005A310000000000000000000000000000000000000000000000000000000000005A8E00000000000000000000000000000000000000000000000000000000000005D3000000000000000000000000000000000000000000000000000000000000062D00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000006646000000000000000000000000000000000000000000000000000000000000068D0000000000000000000000000000000000000000000000000000000000006B3C0000000000000000000000000000000000000000000000000000000000006BF10000000000000000000000000000000000000000000000000000000000006EBC0000000000000000000000000000000000000000000000000000000000006F2300000000000000000000000000000000000000000000000000000000000073EB000000000000000000000000000000000000000000000000000000000000776500000000000000000000000000000000000000000000000000000000000077B00000000000000000000000000000000000000000000000000000000000007B360000000000000000000000000000000000000000000000000000000000007BFD0000000000000000000000000000000000000000000000000000000000000C550000000000000000000000000000000000000000000000000000000000000D7500000000000000000000000000000000000000000000000000000000000025FD00000000000000000000000000000000000000000000000000000000000029E10000000000000000000000000000000000000000000000000000000000002A680000000000000000000000000000000000000000000000000000000000002D9200000000000000000000000000000000000000000000000000000000000040850000000000000000000000000000000000000000000000000000000000004C5E00000000000000000000000000000000000000000000000000000000000058A600000000000000000000000000000000000000000000000000000000000058FE00000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000005B690000000000000000000000000000000000000000000000000000000000000639000000000000000000000000000000000000000000000000000000000000065E0000000000000000000000000000000000000000000000000000000000006FA9000000000000000000000000000000000000000000000000000000000000701D00000000000000000000000000000000000000000000000000000000000072FD0000000000000000000000000000000000000000000000000000000000007301000000000000000000000000000000000000000000000000000000000000739700000000000000000000000000000000000000000000000000000000000073A700000000000000000000000000000000000000000000000000000000000073A800000000000000000000000000000000000000000000000000000000000073D600000000000000000000000000000000000000000000000000000000000073D8000000000000000000000000000000000000000000000000000000000000741A00000000000000000000000000000000000000000000000000000000000077B10000000000000000000000000000000000000000000000000000000000007BFE0000000000000000000000000000000000000000000000000000000000002C1E0000000000000000000000000000000000000000000000000000000000005B7C00000000000000000000000000000000000000000000000000000000000065C90000000000000000000000000000000000000000000000000000000000006FF900000000000000000000000000000000000000000000000000000000000030B60000000000000000000000000000000000000000000000000000000000005658000000000000000000000000000000000000000000000000000000000000576200000000000000000000000000000000000000000000000000000000000058FF0000000000000000000000000000000000000000000000000000000000005B620000000000000000000000000000000000000000000000000000000000006E9800000000000000000000000000000000000000000000000000000000000072F800000000000000000000000000000000000000000000000000000000000077470000000000000000000000000000000000000000000000000000000000000B4F0000000000000000000000000000000000000000000000000000000000000E8668008BA8359743A0187E6BA85161E1222BD37A6033453E25C6F15CA1C38875FC386484B56F3AA9C9986C6C7BFDEDA3910DD7AA8306351B275C3F98681260CDAD01036607FF82660A844E6D7810830771CC94751949CA0E82DA14F6CE1161640684F284E87BA2610F333C5225E837F289EA46A71831ADC83221A3D40561DDFB4C11DAA5F51F8C4ECF017B6D6DB908817FDB4DC0B6B2602E76B6D4662B70D3BD137DC28B313939B09B01037D07FF82C5C0845E1CF67A8312387C9400000000000B69EC332F49B7C4D2B101F93C3BED806A1045041533A3278F3F9141D5F820A184EA4B017FCE238254CCCAD9E86B3714735C7310C7E940B443E6A9B530D1DD532A88F31AE01EFD7273D32D67FF5D75E776614D4517FA65082B66F6CB5CB36E02933CD042F56B26EF010382040A07FF82AFA485E8D4A51000836ACFC09455EFAFFC2764389A08FFDFCD36AEE2C30610D42C80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000B64087573E4FCAAC4BDDAD8F7FC7A39E000008E90205060904080300020701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000213C66BEDD0000000000000000000000000000000000000000000000000000002168BF6BDD0000000000000000000000000000000000000000000000000000002168BF6BDD0000000000000000000000000000000000000000000000000000002168BF6BDD00000000000000000000000000000000000000000000000000000021763F971F000000000000000000000000000000000000000000000000000000217A255C9F00000000000000000000000000000000000000000000000000000021A93FDBFA00000000000000000000000000000000000000000000000000000021A93FDBFA00000000000000000000000000000000000000000000000000000021D41C2ABD00000000000000000000000000000000000000000000000000000021E2B58F940000000000000000000000000000000000000000000000000000000000000004A8F7854880E785E9C0CF2ECF44C0907D9838F280BC04856FB48B7762A2D9F371B89A6EFB61A806680695B2DE0F1B7B9546224B2ED0DA39A6D7B9FDD1A816D7C3B4EB5595BC80A47DB06010FDAE4C6C83D62C1046CC0AF19654EBCCB363CA4EE65029CF2813093F0AD56F7A33C5D959F0C31FF4DC75407C7974E304D96F7F573700000000000000000000000000000000000000000000000000000000000000045143FFFF5399DD22BD787F0E3A46D579DA1C99DB37621098AA09DB52C41312DE3E0F5979421308B64033C4EDC5F9124C43ECCAED3740BF45A9C88BF1C3A78F302F180A611974CD99A358F28BDEAA33C36A63926A96AC347FB9CA8D47686C038A7F75D9686CC1A2A5DC338C67BC3BC5F3A9B461F29F61780ACBD8038BFD05341D611ACC04A3C5ACB4C2A0180955C3E43054853164EB66158EB84CA2CA722CCA701C9B12BF20299A0A523CC2751C3D342B1CD2EE7460297EDFF38C0A4B87FF3DD8000382014707FF62844E6D7810830E6BFA94EBBA467ECB6B21239178033189CEAE27CA12EADF80F242432A000000000000000000000000BBF9DBEFF9381650F99C6D780E4241291F9906260000000000000000000000001D0913C39ACD43523E2ED36D5EFA5730E2AAF8DA0000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002ABDD8585609EB7C81C220A3F6B227AEA87FEA9FB4A49B48CB9FF85B1ED3047438FEE605EF228A02EF7611FB4609FE486BA5A823F488CEFE81DD140079811C05010382010907FF82026A844E6D7810831F59E594F87CA9EB60C2E40A6C5AB14CA291934A95F845FF80677956F100000000000000000000000000000000000000000000000000000000627E1000000000000000000000000000000000000000000000000008199999999999999900000000000000000000000000000000000000000000006C6B935B8BBD400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004FF2E261B8657835801F27FE14C81204847DB45522B02A0E628723E6D6F57EBDAFE548FD60B1F4785F0B59A718BABE0244EF7E7EABCFC72644B12DCEE79022B5709991AFD90C84B764010382010A07FF82313E85174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80742E9E0F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE5F4788B1DAA0574F32F9D52C7A0317E17FC44255C680DACC4466E43065811E9DBC42A670095CB919E161740D663290B7117860C9A762BA038C0ED91C16FE831984E000381AB07FF8301979E85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014DC00001D4C0022162C01D3EC8400000000000000000000000000000000000000000000000000000000627BE4C9117AAD5B926A8F6A5E12D0FA97E20DB567E06AFC7A02A888C44B720EEA5F98E43D92F8C6D94251059F9FA268A507CBA3D0F1F1EA86A21A6F300D292B96A94BE3010381C907FF82017D844E6D78108308A83194737EAF14061FE68F04FF4CA8205ACF538555FCC88070E419450000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000060085DC8B272FB0FAE07F377563EA28F5FB345AAC95774C1746062A038CA59DE43E06F5744C12DB579A2B4E63F32076A2075F386638275C4BFB2E60E31D7DFDD28A3010382010A07FF82313F85174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80742E9E0F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE5F8979762DF4DA96423DD5BCF94EB437426542868E4044C13DD34B041ABBFBF57442AD14B5A0E9CC4205F65F0528D07C1F77B7E9616190B71909235AA0DFEC9535D000381E907FF8228D7844E6D78108313D620946A186D6D8B87EEA2F14964D9C0F0313DB16D1BA7804E86BA3C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C7CC700000000000000000000000000000000000000000000000000014C66EDD22EC2E0000000000000000000000000000000000000000000000000000000000627BE4DE9464F8B063AE7A2B4A82F540AF873996F038E508F31DDF8B927BBAB0273D6FE21922A78945A9169150A3049B7793E8E9F17F90CF196A0B940563507ED7896503010381AB07FF8301979F85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014E600001D360022302601D46D5800000000000000000000000000000000000000000000000000000000627BE4CCCFC95166D6F6E3CD7866817298535035EE9925415E17CC374E9B737DD7B8DA2149C0051F97C54F92231CA1F0966C08194DDC205E1032A148B86E147B63FD0EC6010381AB07FF830197A085174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014E600001D360022194C01D3E15800000000000000000000000000000000000000000000000000000000627BE4CDB888DC07B629ECED9ED535D3716F7402E12048C2FE9C588B3865D6F8BE411A9E2A45A75D0BDAA56BA8BD7342CC37EBA435758E501F52170785578A6EA65E52AC000382010907FF822EE9844E6D7810831E848094146C57ABB43A5B457CD8E109D35AC27057A672E2807DBDC22600000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000000000019001BBC000000000000000000000000000000000000000000000000000000000627BE5300000000000000000000000000000000000000000000000000000000000000000A182A75EED9A95C286457A5ECDF4C9FA566664333AFEDA86085381BF073B3F3025397F8CF5D7C0E83E9F60852530B338E6ED5FE0C3B01831C3EA6FD06AD2BF0E010382010A07FF82314085174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80742E9E0F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE5FC681B327D3D444926F5216DDE665B03F4640085343785F3508B4F1AFECE6D8B235B6C7CBC899337313BDAC81A2F2E5A70698BEF7631F4980629E4D11F07848F34000381A707FF11844E6D78108309E98C94FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980095EA7B300000000000000000000000053BF833A5D6C4DDA888F69C22C88C9F356A41614FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62BB612DA241A4BB2669BCA9D83163AC39929077500981CA61D0399E99C4515C6D7DAADB774A5C9DB76D3A4D7A52CCBB55559BAF5ED014B91357B659ABD68C1D000381AB07FF830197A185174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D360022321A01D47DE800000000000000000000000000000000000000000000000000000000627BE4CFC22BDBBC6F2C4885A666710A3283D616744A62F2A21E34D85D6C03E543D453932C2A74793A9FA6341BE6E11D1BCC9FA54F9C2486715A006E62AABE2F40E8F09001036C07FF02844E6D78108307A120943701F04E25B57E549A2A348C18E2D925C28056028804D9D75F96E913BC005AEAB1BDBEA9DEAE9156834BA4917CA950B9029CCB4C9C5659186228C4D406B244E8FA0485EDBF204BD25BF9A8E7B8D87EAF7B1B6DAB888445C4489785CC38ED01036407FF36844E6D7810830761FC94455418F109C652727B13141CD6E3594A70CDF69A1C0FC46C04620F367C54E13A6F94EA439388FF005D78EE5F2A3843A3F174BFE54B5801C504D446C09AAB962E9B67C31B5E4F50C145F87BE52B00EB71C1E8D28F89A3010382024907FF8201CF844E6D7810831E456E9432AF3A08CF8ACDF74D91FFD80CE73BBB0FD0639B805B5971AB00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000CD509DD3A00418CBD7DF084B9CEAB912CA5D97DA65BF63332DFF306784C411FCA54516E6514C1253686EB893D47EC397AC7F88E5B3FAF2AF13CCA99CDD4BAB825636611AD3F5AC8D18521EB5BD8D4D11E9B50DC177A5381122C0AC0D7B9615490C5B85EB977589440BC4FF6896B955049D24A0D2E0C98D5EC672436D12177F2DC315EFE6DC2D97DCAB7BFA9591603D7F5C19AE89D5FD8C76431D4D212466C5A27204132B9AC46B02F07B03C8F8EE5DE82F2C9862F16A65D1117E889A271E2EC120FFF6C90854BE13DB37DEF52BFFBB52698D1B2C0A49D4644EFE8362C3A214459A3328F798E25D67A622985AC8E50C61D5FEDAB11A91C00DBF580AEF6E805C68CA57677BE68F8BAF2D85CC95272C6CA2A258B463F094218E652E96C88B99D9BEBFAB816A6D1D077C004805DD2A1CC2C5D5B7F4621CED203588D7A17E12044439100BEAF034CC0F7586BDFB3740F16D6BFC3AD9D6E24A749A5FEAC721A080B8BE1F5AB0C60338882A4EA601B9E59549EF04B15A49EED7245410957CA0D543FDCA8C18FB653A781971B34ACB16982772706739B082D31A36AA717F7C9703EDFB2A961C99E6A22AB6AEEA6E8234A2DA5B861C8F3622CC49CD1018AC64C6AEDE8AF46000382040A07FF82A4FD85E8D4A51000836ACFC0942F45A77C5024EB546E9E7F445F266C0D3E71E61680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000E2B45FCF3F7E0DDD1B2470F60F3A1F64000008EB0306090400030801020507000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000037670B6000000000000000000000000000000000000000000000000000000000376B9F4000000000000000000000000000000000000000000000000000000000379907BF0000000000000000000000000000000000000000000000000000000037A10BB70000000000000000000000000000000000000000000000000000000037A2603900000000000000000000000000000000000000000000000000000000380D29CA00000000000000000000000000000000000000000000000000000000384EBC8C000000000000000000000000000000000000000000000000000000003867EB9C0000000000000000000000000000000000000000000000000000000038CD418C0000000000000000000000000000000000000000000000000000000038EC24C000000000000000000000000000000000000000000000000000000000000000042782472240EB5735E878DC6920CC3A7393C8A82B25322ECF51F741EF36A837C56FDD6DF92F2DD2D70E64133490343F115145AE2E233032748637DA29DCB4BC1684BC039C266870042F7623FE7CAA4E0ED5352553F5A70704C090E7B23DD99EA996AB6218621B5CE97C982D14A683EFD014FE374B34EDB913E1EE57CB36954693000000000000000000000000000000000000000000000000000000000000000460D07FACACB2CD539BF8189F84A43D87209F7830AE4742B21B6CF24152AE743411DE028AC33DC98EBCCB92EC174C715C537B1816D1569A7CFF2765D488A00027050CA2014594E9B22B77F309F7F085A0054195BA11F6F8FBBB7D917F796CA0174760B25D39C36EE4CE750589DB45289A3812EE34D1938AAD125E0BA605051DFA22CEC3D216F7B51A18B22C4D470929683933C9E20A11B002CD35D0E1DCE1BE5105B8257BEBEE7C9796F9DAC060408149E6BC36538387DB6FF446B6F15772443F010382040A07FF82AFA585E8D4A51000836ACFC094EFC5061B7A8AEF31F789F1BA5B3B8256674F2B7180C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000E193445CE0BAE19053668642A3CB19770000B5800207030501090206080400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000001FC999C8000000000000000000000000000000000000000000000000000000001FF69626000000000000000000000000000000000000000000000000000000001FF69626000000000000000000000000000000000000000000000000000000001FF69626000000000000000000000000000000000000000000000000000000001FFE4447000000000000000000000000000000000000000000000000000000002001CC2A000000000000000000000000000000000000000000000000000000002034ACFF000000000000000000000000000000000000000000000000000000002034ACFF00000000000000000000000000000000000000000000000000000000203F014000000000000000000000000000000000000000000000000000000000205B7C2E000000000000000000000000000000000000000000000000000000000000000480D490FB7FB38F54EDE5AA4BC50E95EDCFC6743E13ADF2AA47FD79844F5B45CF817A6166C7FE84688044AECD2FFB978942E6FF382291D9A53E89207AB2BE59B5D067CBB6333223B80EE3591765E4CBE4A6F74BDDE9DECA0B6EBB9EB24A9AAF408D2DC40AF2BCC2EF5FC5D382A4F1D997349AA5E9DF816E09B97572E55A6FE065000000000000000000000000000000000000000000000000000000000000000402DB6751AF3B141AF1051FDE0CD06C1ACD6AA9A9E4C966A245871383D8CDF91B352697B675C959575213221D6470E8B06072865E21D5D66D9F485664C0328655366DFD1DCE69DDE171A2FE438AC49C17EF3895AD6AD65D9743CB658CDE59921A6D948B7DD2912099610EAE44050285A1F87E3BC836F701066C448F6B6D7DF604BB1445EB9781026935B2B6DC903DEE6F2F6F988BF8FA2141F154510E2685EB6B73195EDA5635A86F43C7C3C8B3B85852088FBCB69DF416C03C506C9DF54DE895000381AB07FF830197A285174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D360022194C01D3D5A000000000000000000000000000000000000000000000000000000000627BE4D14B45CDF2FEF6005A15A9A64D7B822E7292257ADC7BF8D4406AACC4C22937BC1502BE4920406B912F81121502F2B28F25B9DF807D2A3C6A0A0ED5AC5CA5163004000381AB07FF830197A385174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D36002238F001D519D800000000000000000000000000000000000000000000000000000000627BE4D2253F368432DBCE3E80AF7C12E1EBA24A4AD14372D48C008E12DC899B4276988076EEE8426AE85B485D864EC1B9BFE68032E2E87D3EC41DD8046C2A52D87939E0000382010907FF822EEA844E6D7810831E848094146C57ABB43A5B457CD8E109D35AC27057A672E2807DBDC22600000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000000000019001BBC000000000000000000000000000000000000000000000000000000000627BE5350000000000000000000000000000000000000000000000000000000000000000DFD617AD79E1D73D5788ADACAD064EF11B1D5F3FF32C4F9D552B83F92FCA7776002CF8932F52E0D9274E90AA9C980CBD40182C873C44454FAD225354C2D56455010381E907FF8228D8844E6D78108313D620946A186D6D8B87EEA2F14964D9C0F0313DB16D1BA7804E86BA3C000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000014D1120D7B16000000000000000000000000000000000000000000000000000000000000C7C8F36C00000000000000000000000000000000000000000000000000000000627BE4E6BB51D6619F5DE25DBB6081797DDADF9BD41E87697A0FD0F799A0476DD014939C6CA5790987AC59D8F6610695609C976AA615AD5F031D8711B7AC0C3FFCE7C1F6010382012907FF82026D844E6D7810830D4B1194737EAF14061FE68F04FF4CA8205ACF538555FCC8800A0E28D400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000262100000000000000000000000000000000000000000000000000000000000027D700000000000000000000000000000000000000000000000000000000000005DF0000000000000000000000000000000000000000000000000000000000007454B0645E9966F6BC0E32C3475918CE24300AC2513F7C5C80EBB5C5D0ADA32F5A6943503AFE5D14C4EF33EE544397DEC6776556C8E51C58A348CD540169C6F88364010381AB07FF830197A485174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D360022371A01D4D32E00000000000000000000000000000000000000000000000000000000627BE4D328B101F5B70F1E4A43F9143F85897737ABF522D09DA447028A1154BDEE704C5F35ECCF513999CF5676F8F17CBCDB4E38B33FCFDA8284D048FF780DEEEFE7166A000382015007FF0F844E6D7810831065D0941B02DA8CB0D097EB8D57A175B88C7D8B4799750688164754702DDEBEF3007FF36AB500000000000000000000000000000000000000000000000000000000D41234DA0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000EA0C6C2B9E5A9B96CFED67A97F0FCBCA320D02D700000000000000000000000000000000000000000000000000000000627BEB78000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC81DAAB14275C61637CF18138CA9B8FF13E9560F23D56E4508CBDABCBFB4D4F3EE080DEC21A5A57C4B9CD6994A9DD0019F5B915001931D5D0A3172F762E00678AC010382046907FF820A9A844E150380833DEE7A94737EAF14061FE68F04FF4CA8205ACF538555FCC880CEDEC2FF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000C000000000000000000000000000000000000000000000000000000000000003A00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000024F0000000000000000000000000000000000000000000000000000000000000251000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000005B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000005B00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000163173073ACDF9D302EE3B05238C6451BE894E23A41656DDEA5D68F332B1174C40183BB94AD90CB905ECB50DFD5938746CC4B37054880201DA62A4734CA54C5FF0182040A07FF82A2EE85E8D4A51000836ACFC0949B8DDCF800A7BFCDEBAD6D65514DE59160A2C9CC80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000017E1DE687DF661FD3F7EEB0D2CD65F500000B5750602060104050803070009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000002C9EDC57000000000000000000000000000000000000000000000000000000002C9F9241000000000000000000000000000000000000000000000000000000002CB290E0000000000000000000000000000000000000000000000000000000002CEB1623000000000000000000000000000000000000000000000000000000002CEB1623000000000000000000000000000000000000000000000000000000002CEB1623000000000000000000000000000000000000000000000000000000002CF65ADB000000000000000000000000000000000000000000000000000000002CFC2AC6000000000000000000000000000000000000000000000000000000002D5BF040000000000000000000000000000000000000000000000000000000002D5BF0400000000000000000000000000000000000000000000000000000000000000004568156FCC42123F7AF3667687DC087B9E1B95C96825243C9F66C7258C5203E9EA66F0BBECD73BFAE786E836AFF93F89A64DE8367B7C8BE67BA746D60A8C057690252ACF6D3B4A98892A4CE4ACD425D878B577B6D4B214C8BA44D279A58FE48848B5117CAD936F918E1BE7E38DF9896042FBB6D56CCA72257F7DEB027012A32CD00000000000000000000000000000000000000000000000000000000000000041D893B52B2EC5ADE20347BD43FCC3480FD44E5238D78BAF60033240A8F99B6182164B6CD766FC90A00703F1530BCD6442FC5EFB653E23F3AB2265DA7ADDBED1F01DBE29BCB621784A6410F2687D44957D387A307B97EF70B6C9C0BB4B1D738210999A8C37DCADEB75912E4BFC3B4618C9CD9D61FCC075E89DA01C4E751BF841D8A9C24686BDC1672CBEE7116AB3A67C16F44D5099103142B6E62A57F45A0D1721EC8BAA72DE4F80EF58A47A9F5D29F64839A2388A5659CE22456C36ADBAE1FAE000381AB07FF830197A585174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D36002225CC01D3D5A000000000000000000000000000000000000000000000000000000000627BE4D490D7D289E9BE10626DB7F5D86BFD30CD294B3F2C266D5186B1C2A417C799EB231DE46BA39834E98F9C52C8E4D9764A289399CB39DC1D4505C964CBE9A1F02D87000382040A07FF82AFD485E8D4A51000836ACFC0948C4308F7CBD7FB829645853CD188500D7DA8610A80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000326225800997DB72917393A973E36C5300009FA70505000601080309040702000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000001475C7D390000000000000000000000000000000000000000000000000000000147EB7EF10000000000000000000000000000000000000000000000000000000147EB7EF10000000000000000000000000000000000000000000000000000000147FAA1080000000000000000000000000000000000000000000000000000000147FAA1080000000000000000000000000000000000000000000000000000000147FAA1080000000000000000000000000000000000000000000000000000000148A438450000000000000000000000000000000000000000000000000000000148B838C00000000000000000000000000000000000000000000000000000000148B838C0000000000000000000000000000000000000000000000000000000014DC423600000000000000000000000000000000000000000000000000000000000000004B0DF982A56835C7EC9F07CFB83F92B340F8E5928298CF1AB782C40E34856D2C615C1BFA82AEA63505E702F7C3FFFC4ED78A3ACC266E8B73E76D39F3A503DE73011DA23517341E7AA9B06BD78A53DFAF70AC9CBF9AB024129EC90655F16B2D54010A3CFF8E4D74DA89163AF15D5001F7DBD284461CE26C1DC8F2098A789683694000000000000000000000000000000000000000000000000000000000000000472AE86E381371785BD4EA9A7C83B7E06A493E879C69D37B4171C83F0027FFC451CD1EE223A48EB83B14DF6C04F4A2E7A214410DB591B357ED3B3505633DEB44D48885FC54F8B4C7A3FBE395C361CB4CFF432421682672C952F616281F5DD067875DDBEE27EF3D24135AD2D7E01C27AAF043C89BCA98D632982A0561069B218403D97BFB1E0834EA5E1251893CE62E6584FBF5EAB17EE81A477378D313F80C37B071D921BCE55B289A504A06E325179F09E1B62424E481ACEE80A934E8E871B09010381AB07FF830197A685174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D560022288801D3D98800000000000000000000000000000000000000000000000000000000627BE4D600B492B974030146D70E12AE53822560595CB99E152AC03E05456A1AD8D84E9C4751ED17F035285BF21E6305ECCB7E808C9181DEAAC68A9353A72026BF2E6A4A000382028907FF820545844E6D7810831BED2C94737EAF14061FE68F04FF4CA8205ACF538555FCC8800A0E28D40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000F000000000000000000000000000000000000000000000000000000000000058300000000000000000000000000000000000000000000000000000000000006CF000000000000000000000000000000000000000000000000000000000000326200000000000000000000000000000000000000000000000000000000000046D3000000000000000000000000000000000000000000000000000000000000524800000000000000000000000000000000000000000000000000000000000005840000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000058A000000000000000000000000000000000000000000000000000000000000058B0000000000000000000000000000000000000000000000000000000000006076000000000000000000000000000000000000000000000000000000000000639A000000000000000000000000000000000000000000000000000000000000639B00000000000000000000000000000000000000000000000000000000000065A600000000000000000000000000000000000000000000000000000000000006C900000000000000000000000000000000000000000000000000000000000006CE15B6B248508D5909CDD27FDA391C732F9A31947AE0E1ECC3013B8FAC007BD2B3683B835FC6312DA45C163A7B14BAB24E712BCB387DBBD078AAFAD9E637792A36000381AB07FF830197A785174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D4C0022285601D4D54000000000000000000000000000000000000000000000000000000000627BE4D81AE5899D4C97432AA7DBB15661A420AFFD75BF107BB893D67EA4F9ED31435F74787DE705085CDFDC6EBF1039E89FEBC152117D6056B6D318985AD53AB057CCC400036707FF0A844E6D7810830779B494948E4A5D2135476EBE533A1E35EDD05A1F0D4F09830598230ACB24EBE535699C10135B6AE5BADF243DC00EB3DC445F8A602BCEFB2D94FBD70356E5394F563C1ECC7054E41258E813113A4FBCBB35007FD03E67619B0E8358AA01038201E707FF02844E6D7810830E2CBD9437F9AE2E0EA6742B9CAD5ABCFB6BBC3475B3862B809F330727000000000000000000000000F6C9EBD49C948888B921F150B03CF63A7AB58A3A00000000000000000000000000000000000000000000000000000000000000FA0000000000000000000000002913E812CF0DCCA30FB28E6CAC3D2DCFF4497688000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000207922ACF00000000000000000000000000000000000000000000000000000001FD2DF6C000000000000000000000000000000000000000000000000000000000627BE72B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001F2C28C9D00000000000000000000000000000000000000000000000000000000627D3653F4ED24D1698E4F63149B154325D7D922B1E867BA8628135D260A13FC2E1E57977A02BAA92B6D2590EB566E1266BB9CB623DBC56B953EB31A37BE9A23C22BFB6E010382012907FF822EEB844E6D7810831E848094146C57ABB43A5B457CD8E109D35AC27057A672E28043C8D33B00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000019001BBC0000000000000000000000000000000000001ED09BEAD87C0378D8E640000000000000000000000000000000000000000000000000000000000000000627BE53926C52ADE52A66155D3C36DEF50A5AA167EF1A301F2E2D7EBB67BBB1E494E026460FB5D0D1F60E481144B20D42CA25DF4157ACAC5E120288DDD4F5FE5C4C38006010382018907FF82017E844E6D7810831024A594DA3CAD5E4F40062CECA6C1B979766BC0BAED8E3380F68FA578000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000166B00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000019A960AB9D7348F4C44E3F3C21EA1007735BECB10C1E32B61901A68C6E4003F846F0416B0818BDA96164BCE70952DCB3D4290115BFD3CFED4C38ED84236D006F7010382015007FF15844E6D781083107F90941B02DA8CB0D097EB8D57A175B88C7D8B479975068802860C03A780AB3F00FB3BDB4100000000000000000000000000000000000000000000001B1AE4D6E2EF50000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000009FED457758D8F47781D55F1A7D2645F417C18EA900000000000000000000000000000000000000000000000000000000627BEB78000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000539BDE0D7DBD336B79148AA742883198BBF60342528A069A856E5B49FC942ACD2F250EE06599F27566208F5EAB3D9CC9DB961532362361B84C6DFF6E700A984C37AE35D6D69ACFECF47A853B80157C7F32F7426100038201E907FF820527844E6D78108315453A94737EAF14061FE68F04FF4CA8205ACF538555FCC8800A0E28D40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000015B000000000000000000000000000000000000000000000000000000000000015C000000000000000000000000000000000000000000000000000000000000015D000000000000000000000000000000000000000000000000000000000000015E000000000000000000000000000000000000000000000000000000000000015F0000000000000000000000000000000000000000000000000000000000005AA40000000000000000000000000000000000000000000000000000000000005AA6000000000000000000000000000000000000000000000000000000000000062C0000000000000000000000000000000000000000000000000000000000000F3E0000000000000000000000000000000000000000000000000000000000000FBDEFE35904EC3D8808C8A97BFF2865A514892A26D137D68C24B52087A1034C91AB52575770A2F621A855CE5900157BD2ED40FE679A20317F4165ACF8B0A4F3C846000382024907FF820133844E6D7810830CA67794DA3CAD5E4F40062CECA6C1B979766BC0BAED8E3380F93309D10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000D0000000000000000000000000000000000000000000000000000000000006170000000000000000000000000000000000000000000000000000000000000616F000000000000000000000000000000000000000000000000000000000000616E000000000000000000000000000000000000000000000000000000000000616D00000000000000000000000000000000000000000000000000000000000060D500000000000000000000000000000000000000000000000000000000000060D400000000000000000000000000000000000000000000000000000000000060D3000000000000000000000000000000000000000000000000000000000000475D000000000000000000000000000000000000000000000000000000000000475C000000000000000000000000000000000000000000000000000000000000475B0000000000000000000000000000000000000000000000000000000000002A6C0000000000000000000000000000000000000000000000000000000000002A6B0000000000000000000000000000000000000000000000000000000000002A6AF6E768EA5B27A557EF81584C1F6FE0375240F0FF6562808217F69AA3F0E539A7198C6A145960BF7C8E6907E967380FD070EA261AEC4E6B5652D0799C1D8437B3000382040A07FF82AEE085E8D4A51000836ACFC09478F28D363533695458696B42577D2E1728CEA3D180C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000220757267D6C71FC0E42C3B92AF80EFD000077F20200070506030408020901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000075518540000000000000000000000000000000000000000000000000000000007551854000000000000000000000000000000000000000000000000000000000755185400000000000000000000000000000000000000000000000000000000075518540000000000000000000000000000000000000000000000000000000007551AAC0000000000000000000000000000000000000000000000000000000007551EF80000000000000000000000000000000000000000000000000000000007554FAE00000000000000000000000000000000000000000000000000000000075590A400000000000000000000000000000000000000000000000000000000075590A40000000000000000000000000000000000000000000000000000000007560CDC0000000000000000000000000000000000000000000000000000000000000004541C6A38BC0782452A330CDEB17EE3DAAAD780976CA8AC0C0004096A9035660BA9D9F88136B9F6BAF1A53774F4E90FCED7E74CB67824035CA8D5663BEE091F43133B7AE35A13C286AE51C8B9FE9CF4ED651E72D8A0165582812DFA8285A2B3E0548E1C012669C3F9FCA725135E28297DC8C369C991E7B749E1BE39ECE152F3F00000000000000000000000000000000000000000000000000000000000000004783AB4485F3E7A450C6E740319B37EB267939DF3E11A108E4AFC7DCFE07CB7AF0B7597D2DDF53C2994EC3D47FF8CD0A9BD5FBB0C142BDE54F851F7566763292A232341473D7985A8F467F10879EAA691DEBD9BF8DFE7AA64704A96E9ADEF77A16F636A2EF612F89AEDBBA09F292A72299AC44D5F65C0BF4FBE28AA7049E4B78AC58226950FB41D824F1692634D1367173902B206FFABF8134853AD46E9ED81AE7976B744F85FD14AB40BABD6D35F6EA79EFD754DCBB4C11945B0875DBAFA9CEC010382040A07FF82AEE185E8D4A51000836ACFC094B58AFA4BE9B13D896E81D5355C961D2C3317209980C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000008BE4FA88139D17456DD981A86C17690300018DD90608020900040607030501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000004F3D0AB4EDD467F58000000000000000000000000000000000000000000000004F3D12F2D4FF74160000000000000000000000000000000000000000000000004F3D19C3AA41DBAB0000000000000000000000000000000000000000000000004F3D3502D97A310C0000000000000000000000000000000000000000000000004F3D66B78FF3B9E00000000000000000000000000000000000000000000000004F3DE4607305F2E00000000000000000000000000000000000000000000000004F3DF3009BCF2AA30000000000000000000000000000000000000000000000004F3EB3C024E72DA10000000000000000000000000000000000000000000000004F403091B2172BF50000000000000000000000000000000000000000000000004F4058CA2EC25B1A00000000000000000000000000000000000000000000000000000000000000004812E7440D77F2DDC113C769DAFC9E48219038268EF3FDDEC042ED49161EA1D264553B54C77853F18F0D0C816386A7FD18D6A5441B94BE0B618A0AFD8FFF399DD1F2EF9B1F5AAC20BF7AB94C7D88FC27332997A7E9B8AA0D109AFD799D69DEE4B974B15AC7C80890F3E0064132D0B83F173662994D94CD09D6E87EF83AB525EAE000000000000000000000000000000000000000000000000000000000000000426C894CBB4D5A910E80C6B3C3F51D0005481F61942A46E031B8FD8CA27C913AF163AA16C58994919010552E73A29B47FD6B174DFEF1B7E4995E7AEEAA262758778B52508A1E1280483FCA07E381F205051F6B4F73FB76B19553AAA6A8F61E6612E15B7555D5B0565D5BB1354532E0F80CEDB1999276F0C69DAE60A582C4F54D52FA22A35067AF84F1C61209F10BD1E37CB366CDE68456870E9E321EF48EBF51B6E8C1A54416FC5009FBC1C9E14BA07AF6E52106D7225EF9E4C6F17B5248B0F9B000381A707FF04844E6D7810830A7A4E945BF946D5D72D5F6DBE02BE9118F37CF394315D1A80AB445A79000000000000000000000000000000000000000000000000000000000000178A0000000000000000000000000000000000000000000000000000000000000002DE271134CA348D0FBEA6CC7245DEBD5EFF999E731A11EECDD7DF3BDAF7DF61547C82973F551262D211E97011EA25713D9FBF882E521D2869CB0AF394B063D759010382034C07FF80844E6D78108314B19294C30141B657F4216252DC59AF2E7CDB9D8792E1B08417B9684D09A44BBB15000000000000000000000000000000000000000000000000000000000000002000000000000000000000000022F1E12E5A31511B5BB995C01A38D805B75A77F5000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000586134AC99EC20000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000033CEB27B39D2BB7D2E61F7564D3DF2934402041700000000000000000000000000000000000000000000000000038A608B02DF070000000000000000000000000000000000000000000000000539D879945558A600000000000000000000000000000000000000000000000000000180B40813560000000000000000000000000000000000000000000000000539D879945558A600000000000000000000000000000000000000000000000000000180B4081356000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE07980792B4C2C1F3043741D30894079FC54EEFD19E12DF7D457FE9C51A303F676A3A70FDF9C741E776DC738EB07749F001248A68DB703A4665AF12A89945CD19010381C907FF8201B8844E6D78108308A8E694737EAF14061FE68F04FF4CA8205ACF538555FCC88070E419450000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000070B30813D00C3AF1387EB2415A541CCE46DCF59B6AACFA3A72A1F28A5D2E648A806B7EE9120018E812A389AC99F48A8D98DE753ECDB98D28E10EA8F456BE02FFCE6301038201A907FF820234844E6D7810830D50F7946AC94B1093D34F5C520688840689354C9248365F802E60BE5B000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000C000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000005B83000000000000000000000000000000000000000000000000000000000000468D0000000000000000000000000000000000000000000000000000000000006C230000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005C9ADDFB2DC3D674D2EA5E3CEFA2F7D1F9CE48FC1F555DDD193D669DFDC0F7BEB2A92E01D83DB88DEFDA0CBB0589C963E420E88051AB1B79176378FAF93A653910003818907FF820265844E6D7810830C55239409F77E8A13DE9A35A7231028187E9FD5DB8A2ACB809E71B0F0000000000000000000000000000000000000000000000000000000000000006D12F648B3DDD9ADF652516B33880803DBEBFA03B758BF7C37B1EC0BE46B39C2E96EDAE88AF1EEE6638D4307276391273B41A6BB005A87759A72155B6184FFEC2C000381AB07FF830197A885174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D60002239AE01D4EFDA00000000000000000000000000000000000000000000000000000000627BE4E5C84C450BEA7095DB0266011AE668E69ECAD655C1B525B03C3F7ED2783427EB5F7A7DB8239B58463FF1DDEF878D4B145C2547C619DB2ACB5D096897F142F948CF010382040A07FF82AEE285E8D4A51000836ACFC0940A4D55347817738166E2EF8302E12F99CFBDDEDD80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000009A03CF545CA136813D36F3E6EDF690C0000008EA0407030402090805060100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000080E151100000000000000000000000000000000000000000000000000000000080E967600000000000000000000000000000000000000000000000000000000080E967600000000000000000000000000000000000000000000000000000000080F030E00000000000000000000000000000000000000000000000000000000080F093500000000000000000000000000000000000000000000000000000000080F3A0900000000000000000000000000000000000000000000000000000000080F8F7C00000000000000000000000000000000000000000000000000000000080F9BB100000000000000000000000000000000000000000000000000000000080FA7E600000000000000000000000000000000000000000000000000000000081064B3C0000000000000000000000000000000000000000000000000000000000000004F1ED553FA6E720C99FFD9C4F944FF97C6F418172D0E26F0DE283A089593E675E8A3883D19D83A6A835540DAC7D7C907BF502443A0C69B34F3B16DBA8617AD817724F7C1272CC97567A528D9B63E7F28EBB9F11FBE0DDBB94A7AE28AAD0A40D80D291DB27FF5496B990F557FDE60264CD163EBFFD062545563F8A2781247B45B8000000000000000000000000000000000000000000000000000000000000000427920A266B4EF5448BB41CB41D1BF08C10806744F38786296023DAB89A422DFC46C11F81A983654DC772AFA6EF6B1FB990424A7B200090280CA699B9845BCED650B0EA9FF3D50223E11055524C359692E8C005E51EDB11B9B79F93917303C8D97854E9ABC35AA3294D02B1D421CFDA9F236DD026F08484227EEE1CD28FB2A1CDF222837BDB6C10B9A4BE0E203780098C533C96960368A2A009393433D9F72B4945AF53AD84B73CA3BAF08037A1AE50DF1F2F21917CB4C391246D892BFE0F22AC010382022807FF26844E6D78108311018894282619DB98F8A43E98065F5B306AE740D6D87A842D0EAD6C8C5F000000000000000000000000506ADE0A94949DB63047346D3796A01C09384198000000000000000000000000642FFAB2752DF3BCE97083709F36080FB1482C80000000000000000000000000000000000000000000000000000000000000954000000000000000000000000000000000000000000000000000000000627B18050000000000000000000000000000000000000000000000000000000062F461FE000000000000000000000000000000000000000000000000000FFCB9E57D400000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000B3430A00000000000000000000000000000000000000000000000000000000000001400000000000000000000000009CD71E219AEEE9EC84AF24B781A7C4CA18FEDEE500000000000000000000000000000000000000000000000000000000000000411E3A7F3327CE8443174815EDC340B4A8721859D76EAEAF629FC2567160D61B634D4829F372269D80A9DB4BF3B62C479C0284A3F3518E901A4F486C3D3073DC8D1C00000000000000000000000000000000000000000000000000000000000000A19F061AF1CEF4D9C8FF54AFE5C2E848E7DA5498B1A8DBAB75C4890B65A6406707E2D598799758EA2FC229D67F918871D51C0F30EA14158B24E0648B9F9BDE5001036B07FF01844E6D781083078D7894A38E444AC30F0B926E5B9641F135B33BBCB2D2CE8758F10C248C0A1100C1E9370066D89D6F99577736CC3A86207DFDFC632123488301BFDCF0E8E5C8C6689F5F0174B363FEDA1FFF7A0EE547D1490398DA0B134E9789165F26824D457F010381A707FF09844E6D7810830BE1B394FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A80095EA7B300000000000000000000000068B3465833FB72A70ECDF485E0E4C7BD8665FC45FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D8BB1EF24DD047C04B0B397E5B24D3E0F13D0C5E7DD2D6EBC17515D34F893E96ECC9334E98815852AFE04C2804F01232EFD6EC51C2F4DFA44F7E21201950129000381AB07FF830197A985174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014ED00001D60002228EC01D47E8800000000000000000000000000000000000000000000000000000000627BE4ED92489E5B143DF1529A53E40ABCD7BE104854B13860E419739752E4575055EECE6E751215C4A9B697EF77C786933A7682E6C8BC317383F0C97AB0A926B644D2EE010382040A07FF82AC5C85E8D4A51000836ACFC0943607E46698D218B3A5CAE44BF381475C0A5E2CA780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000F6D9397093865A569A3B827FBE021B4E00012C140304030100090508070206000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000033F8BB7775000000000000000000000000000000000000000000000000000000340B4E9A00000000000000000000000000000000000000000000000000000000341673FEC0000000000000000000000000000000000000000000000000000000341F0942C0000000000000000000000000000000000000000000000000000000341F464BC0000000000000000000000000000000000000000000000000000000342E82D4BB0000000000000000000000000000000000000000000000000000003430415BD20000000000000000000000000000000000000000000000000000003430415BD20000000000000000000000000000000000000000000000000000003431722708000000000000000000000000000000000000000000000000000000343CE64A400000000000000000000000000000000000000000000000000000000000000004776AFAA6F134FC6FBE04EED7AEEEC3433CA32EA26343617B2E5D6283880D58511469B1BF303A85264865EFEB47129C9532C18D8638CC2CDAC74079EC76BB338B8D18F298BFF266B1A77CA8D12D9558B0949B05146B27328849A064CD71489823D3DEC7D2F0B444C705A5151AAA825EED7CCE7B889FA49BB791C6CFD1C309B8F5000000000000000000000000000000000000000000000000000000000000000462A51B6A38E712A2946FC0A9B37BE09648D663B9950B3401E353A33524FFCAD405919230475BC9D937758D3A9264C85201FE118A3C7B7572D5C83EF67ED426424E74BA8E3C916F319C8996B4C5183CD720F2E420C3AD5A6E6936143FC21E41E9781508C82E4432EFBFC224B95EF6B950411BB739F08F556B45F7AA6C46A13B600122EA9531961DBEECB5FBD6FB33140587DEBA56301E9ADD3EDC43E77D16562D4D1C7D6683B14D93EDA4AC72B1862E210835EB5CBE9C47990D11DF74B551B79C000381A907FF82071B844E6D7810830F424094FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880A9059CBB0000000000000000000000004D710A7A46A221B3361BCA2E524AF4C1BDE44BAE00000000000000000000000000000000000000000000000000000000209F97D9D4EC195E3F79F569EEB4EB3F101AF7357A67E7BBCA22DF7C58553B02A92E4DCE426454D03E65F7FB1F82D177D1CC167D47AECCC65063064684D8E4A65D95BFF8010382010907FF8201728459682F0083155CC09410417734001162EA139E8B044DFE28DBB8B28AD0807A78B9C70000000000000000000000007B2D004EA1C118459EF6C54FFD28C6E1E719B48800000000000000000000000000000000000000000000000001BA7D9552DE28000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000B465370674B4351464A4B53000000000000000000000000000000000000000000D4F64C13BF1ED50026EF6330E38E80D765A0655A100D0DE1CD2852E8DDB31FA5300C77079D902554C6E69AE6145C21ED5B9C64965E2E2107CE924ABD12516D6501038202A707FF63844E6D7810830FBC19941D0913C39ACD43523E2ED36D5EFA5730E2AAF8DA806A761202000000000000000000000000A0A89DB1C899C49F98E6326B764BAFCF167FC2CE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000000441764084100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041000000000000000000000000BBF9DBEFF9381650F99C6D780E4241291F9906260000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000034FD80ABCCCB531AA229EBC0507320A6BDC36484D7B53B013FA791357E4CC4B65B6409561D544FC554C75E08F1FE7CD606B248DA8BA3DE0E4226C2CF479685F60103818807FF81BB844E6D781083088B0C94602E50ED10A90D324B35930EC0F8E5D3B28CD50980049878F300000000000000000000000000000000000000000000000000000000000007C875352EAEDE1C7C1056C00F060572C1FC6795E05C5C852BC71A6C835BD0C02878306AF95A60D81B6FCF8CE2845D4CE80AA53E00F56AAEBC2123600C9C8DECCAA0010382040A07FF82AFA685E8D4A51000836ACFC0943D62E33E97DE1F0CE913DB62D5972722C2A7E4F680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000008E0F2B29E8523A5989D18B3AB350F28A00006C520100020603050908070104000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000005DEFDA00000000000000000000000000000000000000000000000000000000005DFFD1F3000000000000000000000000000000000000000000000000000000005DFFD1F3000000000000000000000000000000000000000000000000000000005E048850000000000000000000000000000000000000000000000000000000005E0B9DF8000000000000000000000000000000000000000000000000000000005E0B9DF8000000000000000000000000000000000000000000000000000000005E1C7C6D000000000000000000000000000000000000000000000000000000005E49F264000000000000000000000000000000000000000000000000000000005E86E4F8000000000000000000000000000000000000000000000000000000005EC0BA2A000000000000000000000000000000000000000000000000000000000000000446084490654130D5ED79FF1F65ACA2579AA0581DE4F5A1179AADBAFEE720A83E610D83C27E814809A483924962230E47DF6F445189647A48DA614A181805A2E7677DAB1C7249D00AACF237E2D1FE730E819386BFAA0502419A7B4E5CA8891C28475C4C1D4E3EADC73E6681FB663BB3C64134F376993C552BE533609D801ADE9B000000000000000000000000000000000000000000000000000000000000000433FABE33AF82BDC41B50854961A053E4474C30D78CAF19D8F5BB5E1C8B52FBBE701713262707F787CD135D0E1D1FF4A79E1CF7B59041985DA1E561B25CF8F4E13F4F9397245432934D8AC9695A4960933A5290AE4E0D346FAB79407760E5CE1D5DCD9EED08A3F862273C0562DFBB08B86B08BEC07054CE35A8056E8A123CA8B70644AE5E1C6AFFCDEEC03B06EBF344EB74C3F8E521DEB0466AC69B1BB79DC2E67B093F2B08A26F403E24C3064AA98EF6026F2DA21CFAF9F635A71DFD52FD05A300038202A707FF0E844E6D7810831268749468B3465833FB72A70ECDF485E0E4C7BD8665FC45805AE401DC00000000000000000000000000000000000000000000000000000000627BE59C000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000E404E45AAF000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000019E1ED4800000000000000000000000000000000000000000000000002AFBE793E404B82000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C00000000000000000000000000000000000000000000000002AFBE793E404B82000000000000000000000000A849344346DDE2D729D6D77FE1F5F7D9B941C8C200000000000000000000000000000000000000000000000000000000BE714EA93CFD38CFBC631D6326EE0CB9FFC18AABFF487C3DE39677B0AE8810E934B2666F3A427FD668182B5E56E9E4E6DD43EC5777FDB8CEF2578F868D6FFA4801038202A907FF82058A844E6D7810831D648B94B9C9ED651EB173CA7FBC3A094DA9CE33EC145A2980B7EEA37400000000000000000000000000000000000000000000000000000000000056530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000005C000000000000000000000000000000000000000000000000000000000000005D000000000000000000000000000000000000000000000000000000000000005E0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000970000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002EA69D5E4EA7C17323A2714FD1E6717FC3B6D301FB87792744FF05E98F5AA089801C9781339AF0F3E30C031FDC0AF3EAA8EA7AFB160C3C61A2B9A05F385CD18A4000381E907FF82214F845E1CF679831CFDE094A96B576F3F117158176E396467D591A1F5DBA9DF8046F83B500000000000000000000000000000000000000000000000000000000000000009E50E7C3F955A0FB95FC054ABD8C21D677E5BB6E4B7D607A92C39379ED5DF7912000000000000000000000000000000000000000000000000000000000000020015123D53C7C5C68577F726C53BC0D981E0D46A7DEF98FEED9CD5CF5B61919C721C3E4D8A7BFE251E16858706028DBD164281729465BF58468CCB145082BEF0F607D8C055CBAA1D5AFA615EEBB2AAF722799A68C05D097D82ED97D4E37451F236000381E907FF8221B6845E1CF679831CFDE094A96B576F3F117158176E396467D591A1F5DBA9DF8046F83B500000000000000000000000000000000000000000000000000000000000000009E50E7C3F955A0FB95FC054ABD8C21D677E5BB6E4B7D607A92C39379ED5DF7912000000000000000000000000000000000000000000000000000000000000020015123D53C7C5C68577F726C53BC0D981E0D46A7DEF98FEED9CD5CF5B61919C72974449A82D3604ACE7D018FD4588FC2019486D58C4EBCB8A5CE720926103B29E70C6B09D4FD1A3E61F9D6690B5622B6AC54BA486202F997C9D9EA71325EC44B3000381A707FF27844E6D78108309304B94642FFAB2752DF3BCE97083709F36080FB1482C8080A22CB465000000000000000000000000282619DB98F8A43E98065F5B306AE740D6D87A8400000000000000000000000000000000000000000000000000000000000000016AB49B814097CA9FF0B3A6045B8C21D5AE51AEE6ED9D897346CFBDADC38BDC387649F638BB0D5B884DB56E5EC9AA9E1A12DB0298BB7A8FC8B9EA519CA83531A2000382040A07FF82AEE385E8D4A51000836ACFC0940D02B6EBA98BDA364953D9B1DEF8EEDC19FFD51680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000090A742BF1BBF80E9C2AC1865869012570001DA980203080705020104090006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000881A04E000000000000000000000000000000000000000000000000000000000886669D000000000000000000000000000000000000000000000000000000000887CF67000000000000000000000000000000000000000000000000000000000887CF67000000000000000000000000000000000000000000000000000000000887CF67000000000000000000000000000000000000000000000000000000000888B21E000000000000000000000000000000000000000000000000000000000889237D000000000000000000000000000000000000000000000000000000000889237D00000000000000000000000000000000000000000000000000000000088DD54E00000000000000000000000000000000000000000000000000000000089C75060000000000000000000000000000000000000000000000000000000000000004D7569F937F6BE94C244243F595068B5ED8C915157B7C559AB44D92234E0B79A14B6341A59F96652D72D5131ACD2C677EFE57CB6F35271D6DDD8B1A8DC507C8F0D3D45386E0C480A2556E2D89EBFB96EA0115EB053598D71CACCADCC2C587BE910983B2FB75F3C794270C15FD97647604140846273CEE464C2E75D353A0B89A9B00000000000000000000000000000000000000000000000000000000000000047531CB0B9DFC34FAA8F9B2DD00AFD891E702DA64AA93BA2B402A15BCC22A2F5519002BB5C4B4B418843D618864F6F9706B6E81462EFE3C422D4B4AE1C11C3CCD1AAE3C5BEE8976716124A8A2DD2B448DD7A7F69E90FC47352210879333F67E00068645F3D7607CF6ED14931B9077BDFBB9C54406AFA10183894A14A9A325743C91DC623E1C84EBCB441CE5DC5ECF0DECDD0D92F0B43B8F20B421D7EE7866092C2330A71836C58F8F87BDD7824D9D3D9F7CC522866EF7182B14697F3338CAA9470003820AA907FF820282844E6D7810832D151894737EAF14061FE68F04FF4CA8205ACF538555FCC880821CAB0B000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000006A000000000000000000000000000000000000000000000000000000000000007C000000000000000000000000000000000000000000000000000000000000008E00000000000000000000000000000000000000000000000000000000000002AE600000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002AEB00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003C3B00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000406500000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052F300000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005B3900000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073CB00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007D5800000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002CDB5D76D50E89B835CEE04802BC3D849AEAD26695BEA5AA42E85A8160CF1D340C8AAE89D437CDA21FC3DB6C57E5ED7323B17EEC45C1DAA431BB2AB4D9CB254E010381A707FF08844E6D78108309E98C94FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980095EA7B300000000000000000000000053BF833A5D6C4DDA888F69C22C88C9F356A41614FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0DB2A40218C6712360068EBC3CA0927DB761523EBF7576E45C6D4F82267F1EDE2F9C0CA5145510AEC6D3F283F715033D0E6E73F34FA555CBB468E62BE6DAE259010381A707FF0A844E6D7810830ADFD094FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A80095EA7B300000000000000000000000068B3465833FB72A70ECDF485E0E4C7BD8665FC45FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF467A4BD5BC1E6B71B660E13D462CE130A71C8D6187F5341677D1A615242EA14B2A436ACBCC90D06363F87E0CEBDCA51C4D0E6C2452F7598FA1149FDCD68C660C000382010A07FF82314185174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80D01FD32F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE631233D61FE89C75A8BB21FC3A65040E1C5D2CD453AD3532FE1385A2D5053471395757CD9C075530E2E4FCC54099F64739E1E63A5C547B6B85CB938EE6328B3CCE5010382024807FF81A8844E6D7810831313E69468B3465833FB72A70ECDF485E0E4C7BD8665FC45805AE401DC00000000000000000000000000000000000000000000000000000000627BE59C0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000124B858183F0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000045797F7AC045EFE662866862247F552C6E4DAEC6000000000000000000000000000000000000000000000013539C9C9CF8D680000000000000000000000000000000000000000000000000000000000239462EDE0000000000000000000000000000000000000000000000000000000000000042FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A00271082AF49447D8A07E3BD95BD0D56F35241523FBAB10001F4FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000137E8DA8341D45898130F48A8D2B059DBA70365106B6FDB41113A462A324766B2B118EA230A553269D0843179CEA78F05B2BB6AD9D19468B2C12B997B2751FAF000382040A07FF82029785E8D4A51000836ACFC094076577765A3E66DB410ECC1372D0B0DB503A42C580C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000001DAF840B23E94D5DCAD494E96683231C000003B90603040607000801090205000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000247455C800000000000000000000000000000000000000000000000000000000247455C8000000000000000000000000000000000000000000000000000000002478B48C000000000000000000000000000000000000000000000000000000002478B48C000000000000000000000000000000000000000000000000000000002478C91600000000000000000000000000000000000000000000000000000000247AA8C400000000000000000000000000000000000000000000000000000000247AA8C400000000000000000000000000000000000000000000000000000000247AA8C4000000000000000000000000000000000000000000000000000000002492573600000000000000000000000000000000000000000000000000000000249B0B2C000000000000000000000000000000000000000000000000000000000000000411A75B53FC3BFE10AC017B87F524D4746275EA1C81EF8849A268A38D86107B5F57EFEAE04C8C10D1C0BC741D27A49EBEC73242598F27F4086EB7306BEDC59039283C45FB79130FCBAF20B4CE40800FBFB573FE2BC224850474FCD99D793E9CF7DC071BBB85A04E64AB273ABC7663A6A816318D68812F9ED5DBB8B90FAB90861F000000000000000000000000000000000000000000000000000000000000000457BC159B822B39A1A52B716C913D221FA488171E4B4C9F9E50285B103D0D5DDC7838F6C302E405E7CF5C76A0F1404E5ADDBACAA08ED8FD4627C7F5E6DE339FE6303C1116B55E0A7BBC5DFAD35806D4ACC03535D8BF0D568561DD97AEE244235979C9EF93BC0DAC4379D3473711847B5B229C96E3AB4FB45F1C6EA003F7F39C80A66704A3B4E5A1E1B19A8A3314202AB056A32F63B2D042459FD339F0A83B487E25123B2DE9801A0F6B190CC44BFC6D230332709D47863D48A1E801E722799DD5010382040A07FF82AC5085E8D4A51000836ACFC094A58474C4F9A3A37DEAE8E6BCFA337E0E9ED699E080C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000499F8B850CC2FC510640D1328C959EBA00009FB50503060500090401020807000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000CF7AC0B000000000000000000000000000000000000000000000000000000000D291F81000000000000000000000000000000000000000000000000000000000D3B7380000000000000000000000000000000000000000000000000000000000D3B7380000000000000000000000000000000000000000000000000000000000D3B7380000000000000000000000000000000000000000000000000000000000D5A7F11000000000000000000000000000000000000000000000000000000000DBAC3A4000000000000000000000000000000000000000000000000000000000DBAC3A4000000000000000000000000000000000000000000000000000000000DBAC3A4000000000000000000000000000000000000000000000000000000000DCEFDA20000000000000000000000000000000000000000000000000000000000000004B7867C587F9177E3FD1B043CF4CC8967913DF65247E172E6E140F1E92F4CEA1DCD2F9F7226EC77B2AEB569791776C8563C02143729D49F6B797BC5DD96F22312212620A56D93F1210A4907EFC2838B81BFD60FC59B5C23B1ECE2EC6E06AD8FD39337A193CB21A4D508B3D16C097CB73A64CEA5C1F5E9A67B27835E6B60DBE64900000000000000000000000000000000000000000000000000000000000000043C717B8EE104A22B71930F02DFBA5877B49FDBBC31CC50C9F1B84EC6EEA9BEC1297CC704E181A899C1981E810BFE4ACE646FDCB4901CC166644DB81484E621FA1C78563FCDACE10AE0696CE3782206DDB6494FF2341447CF522546A6567169233C11F7D73CDCDD11158E28E5F8A1E95F2B26C7810A438372040DD02297D14551EB29A478FD2742302D579AE01F8D7BC4CD54DDAD8303DE42FB8F2CBED054FCF53C4888B59B21596FA1099E8690B60522928D89EBCD43DC5AEF64E29F44C4B8E700038201E707FF3A844E6D7810830E446C9437F9AE2E0EA6742B9CAD5ABCFB6BBC3475B3862B809F33072700000000000000000000000081DA4CB629369E28D70A929AC30B1448861EF30200000000000000000000000000000000000000000000000000000000000000380000000000000000000000002913E812CF0DCCA30FB28E6CAC3D2DCFF449768800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024B66F73C000000000000000000000000000000000000000000000000000000023FA7776800000000000000000000000000000000000000000000000000000000627BE75000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000200CE07F042EDD00CC900000000000000000000000000000000000000000000000000000000627D36782B4CA2377262AD777331E7EFA3B538929E93F9D1C4392C896A1C209587CB5AE35BF0449A2E6C872B44E1A860CF99787BDC7EE89E710903C15605F14A62572318010381E907FF82015C844E6D78108309545194737EAF14061FE68F04FF4CA8205ACF538555FCC88070E419450000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000044F8000000000000000000000000000000000000000000000000000000000000637D946E5177882A6316A3F5F9C6AA5186BA4DFD63AE614500340EBA6971AC1AD671432BE66A96126ED53D30B38D8602411059C6774DFFBF2F0C2B24C1705661DF1E010382040A07FF82AEE485E8D4A51000836ACFC094815D5838677F0F063F7589C1DA44F76241FD0C6580C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000064036BBA5B3C4ADCB822DA5FEB8C970200001A0D0606070500010804020309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000032A6DCE69339E74000000000000000000000000000000000000000000000000032A89DFC659050D500000000000000000000000000000000000000000000000032AB7C8ED0C5E77000000000000000000000000000000000000000000000000032AB7C8ED0C5E77000000000000000000000000000000000000000000000000032AB7C8ED0C5E77000000000000000000000000000000000000000000000000032B09CE9AD859C8000000000000000000000000000000000000000000000000032BC1A3E2A58B03000000000000000000000000000000000000000000000000032BC1A3E2A58B03000000000000000000000000000000000000000000000000032C098624080E9D00000000000000000000000000000000000000000000000003310330C28119DC400000000000000000000000000000000000000000000000000000000000000004ED60864825AC6796740A005FD221BBCFF9512E1AF1FDF9B82EC4497931B28298030F2A92CA6BBDDF89F300F29FF3BFC8FE09DE341AC2942CC5921B42A84A6DB091AAAB505CA44597664A6769B0FDE122A4CDA5973D20061B21E0D91551018D51717B0978FD0FA596478860BA04085C9B344C844DDB7726DDA38BA4773E42D7DC000000000000000000000000000000000000000000000000000000000000000415B266BDB1500F8D691B520054F50F2459D8884BF70A8695DCFF91600A855A536AC7989595F3765696311DFE2907CEEC4E587ADBE51A6161C1D4604FB05415C5363292778D1B78CD5B61AA61055B3E974E82B3AC57A9BAF40DCC57F8D2D57E4D440E0E2A28B78A59CA5847D15DE7A3062C235EA897C39C686CCAACBE8D75034473F201A7473FCE3AE8ABE01FE36C48B7EA83C190A42D96FDAD398B3A3FF9B6E74B06390ACF65F9F999D31B073B2FFBD4707B974570EAC368A4B4099BAFEC45D400038201E707FF5F844E6D7810830F0CE494737EAF14061FE68F04FF4CA8205ACF538555FCC880821CAB0B0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000006F4400000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003BEE5AA94A35F5F9EC9FFB7CAA7DA9CC8A640DC74FEDF35647CB8BFA78F26E6772149B55745A359F4F681959372425D72805DE0EB1CEF38A81F088131C044144000382140907FF822147845E1CF67983964C9194FE7C30860D01E28371D40434806F4A8FCDD3A09880AC16D6AC0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000352D8275AAE3E0C2404D9F68F6CEE084B5BEB3DD000000000000000000000000000000000000000000000000000000000007A121E50E7C3F955A0FB95FC054ABD8C21D677E5BB6E4B7D607A92C39379ED5DF791200000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000012E00000000000000000000000000000000000000000000000000000000000000009E50E7C3F955A0FB95FC054ABD8C21D677E5BB6E4B7D607A92C39379ED5DF791200000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000126000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001A000000000000000000000000000000000000000000000000000000000000003E00000000000000000000000000000000000000000000000000000000000000114F90111A00F15F561E1AF86AE85B7D87C1AF13B451BCA635DCB85129A9219D115BE943EF6A04F1BBA8A2CF7FE57FAADAC47A81D6CA6B62C220B80642DE752DD95644887290CA0A6F1D6C787153A49F418896EBF206EE9BE228E2D5B4CD72451524BFB0AC689B8A003D6083459F214CB1B3D11E7A8DF1FBD180497D0B17DD0500E0B47E26ABA2D98A016D00768DB8BE6FBE736F1CAB1AA2B193235E527DCB6BE69E36255F62184422BA003DC14C80F2F21219AC8961B68DA5906AE266F91FABA39797B376A745EAD2999A02FF8A584DEAC226377C4916840F9F4FA4C52FC4C5F6E33117812A9433B18878880A0586E4235B00C4E841F5B4AA38D8C7482949ED878658DB5948B10D2084C9EA60D80808080808080800000000000000000000000000000000000000000000000000000000000000000000000000000000000000214F90211A0F88DEA8D328D2DF789AD179EE5CBB1512C7F92FF5A13A4DD124DA52F821AEB00A08D455A51351371BC0BE9531E27F7E0F4655315A567DBCC73DB5407C2FB4C9DB0A0AB8F6EB35882BD3961A84FB04D328CA0B34B968A298979D24EA50AAD0F132359A0F19369041CA560998D65F20E45197FCDE91D0F64F6F773F4A854EB39567AD692A02FB26886B2DB7FD061D33EE86E0A55C254374A671C1D2B3A77B6E4072094F55DA001D94CABD99FBEC3193DEAAF9CD63693989241ED235B9A831DA419C158BB6307A09FAACEAF31C7E24AC82368AB8EEFFB76B29EF3222F1B581868B4910BFB6C5D9FA07D4ECD65D48A01E48C8984E911CA4B3F3B201A86C37570BC69A7C60BBB9FAB94A00D69BF3D3520CA8594471511CCCF77632F56775F63A8E1ED4736326018027A4BA059C8B6B922147D816583F2641421689ABC0DDFCA7B9569C1EBF5414F0461ED1BA0A6CF4D8825C9F89A7DD4925EBBA3AC5EA79085380592E860C530254F189E6237A0C7A40DBC54CDED04B66D7B2BF4B548BE34DAE58FE5179590C4E8B58824C9E512A0B5F6FEF3F3C9B0818DA352F7A70B8667C16D5E12FEBAA49B9657FBCCB3004911A0BB952F8BD0BDF8FD16A9A3DC65C5762369ABD1D66BB8319652169C12C9222F0CA013A7704FA6C33D433C5A6D2827B600FE13D8572293ED19AD613A9D9D393B7C3FA0DEB6AB3338D7980B7CE9F1339B6FE2EFE457F0715DAD321DF2B6A77CD41D2144800000000000000000000000000000000000000000000000000000000000000000000000000000000000000D9FF90D9C20B90D98F90D950183427F84B9010000008040102000000000004000008000000000000000200020100000000000000000000000000000100000100108000000108000000000000000000000000000000100000000000000000000008000800400000000000008000100004800000000000000000000050000000002000000020000000000000080000000000000000000002000000000000010000000000000400000000000000000008000000200220540040000100000020000000000000200000200000000000000000000005000000000000000000001000000000000000200400001800000108000100000000000000000000000000000800000000000000000000000020000000000100000F90C8AF9013D940000000000000000000000000000000000001010F884A0E6497E3EE548A3372136AF2FCB0696DB31FC6CF20260707645068BD3FE97F3C4A00000000000000000000000000000000000000000000000000000000000001010A0000000000000000000000000E93685F3BBA03016F02BD1828BADD6195988D950A000000000000000000000000045A01E4E04F14F7A4A6702C74187C5F6222033CDB8A0000000000000000000000000000000000000000000000003A3CFF6C0C520E3F0000000000000000000000000000000000000000000000F5241BFEB19F1A54B920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F4E9DEFF4592C8467A2000000000000000000000000000000000000000000000003A3CFF6C0C520E3F0F8B99429E38769F23701A2E4A8EF0492E19DA4604BE62CE1A06939F93E3F21CF1362EB17155B740277DE5687DAE9A83A85909FD71DA95944E7B880000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045C2B278B08F9013D940000000000000000000000000000000000001010F884A0E6497E3EE548A3372136AF2FCB0696DB31FC6CF20260707645068BD3FE97F3C4A00000000000000000000000000000000000000000000000000000000000001010A000000000000000000000000045A01E4E04F14F7A4A6702C74187C5F6222033CDA00000000000000000000000009D1B1669C73B033DFE47AE5A0164AB96DF25B944B8A0000000000000000000000000000000000000000000000003A3CFF6C0C520E3F0000000000000000000000000000000000000000000000003A3CFF6C0C520E3F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003A3CFF6C0C520E3F0F9013D940000000000000000000000000000000000001010F884A0E6497E3EE548A3372136AF2FCB0696DB31FC6CF20260707645068BD3FE97F3C4A00000000000000000000000000000000000000000000000000000000000001010A00000000000000000000000009D1B1669C73B033DFE47AE5A0164AB96DF25B944A00000000000000000000000003C2269811836AF69497E5F486A85D7316753CF62B8A0000000000000000000000000000000000000000000000003A3CFF6C0C520E3F0000000000000000000000000000000000000000000000003A3CFF6C0C520E3F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003A3CFF6C0C520E3F0F9013D940000000000000000000000000000000000001010F884A0E6497E3EE548A3372136AF2FCB0696DB31FC6CF20260707645068BD3FE97F3C4A00000000000000000000000000000000000000000000000000000000000001010A00000000000000000000000003C2269811836AF69497E5F486A85D7316753CF62A000000000000000000000000066A71DCEF29A0FFBDBE3C6A460A3B5BC225CD675B8A0000000000000000000000000000000000000000000000003A3CFF6C0C520E3F0000000000000000000000000000000000000000000000003A3CFF6C0C520E3F00000000000000000000000000000000000000000000016D1B2840A18EC8ADB9E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016D5565400D9B1ABBF8EF901199466A71DCEF29A0FFBDBE3C6A460A3B5BC225CD675E1A0B8A7262132DB1F61626604A31C3DE81DC1A5BB0F1511DFA70D626AB1B88B52C2B8E0000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000002190000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000220001000000000000000000000000000000000000000000000000000000000007A121000000000000000000000000000000000000000000000000000000000000F9021A9466A71DCEF29A0FFBDBE3C6A460A3B5BC225CD675E1A0E8D23D927749EC8E512EB885679C2977D57068839D8CCA1A85685DBBEA0648F6B901E0000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000017000000000000002199D1B1669C73B033DFE47AE5A0164AB96DF25B944352D8275AAE3E0C2404D9F68F6CEE084B5BEB3DD00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045C2B278B080000000000000000000000000000000000000000000000000000000DD4F49D8A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000142ED1734414D754270ABB7F3C5EA00EBABAED761700000000000000000000000000000000000000000000000000000000F89994A96B576F3F117158176E396467D591A1F5DBA9DFE1A0F5F7EEB9C1FFB10ACED9D0A5354641E9BCCDDE560963D05F8D26AD4A460C89A2B860000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200F9013D940000000000000000000000000000000000001010F884A0E6497E3EE548A3372136AF2FCB0696DB31FC6CF20260707645068BD3FE97F3C4A00000000000000000000000000000000000000000000000000000000000001010A000000000000000000000000066A71DCEF29A0FFBDBE3C6A460A3B5BC225CD675A0000000000000000000000000E93685F3BBA03016F02BD1828BADD6195988D950B8A0000000000000000000000000000000000000000000000001D1E7FB60629071F80000000000000000000000000000000000000000000016D5565400D9B1ABBF8E000000000000000000000000000000000000000000000F4E9DEFF4592C8467A20000000000000000000000000000000000000000000016D3846C05794F1B4D96000000000000000000000000000000000000000000000F506FD7EFB98F14D99AF879949D1B1669C73B033DFE47AE5A0164AB96DF25B944E1A08D3EE0DF6A4B7E82A7F20A763F1C6826E6176323E655AF64F32318827D2112D4B84000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000219F9013D940000000000000000000000000000000000001010F884A04DFE1BBBCF077DDC3E01291EEA2D5C70C2B422B415D95645B9ADCFD678CB1D63A00000000000000000000000000000000000000000000000000000000000001010A0000000000000000000000000E93685F3BBA03016F02BD1828BADD6195988D950A000000000000000000000000026C80CC193B27D73D2C40943ACEC77F4DA2C5BD8B8A000000000000000000000000000000000000000000000000000BAB990591BC6D8000000000000000000000000000000000000000000000F5247E2401ACEA77F9200000000000000000000000000000000000000000000127C78716BCB0D8BA355000000000000000000000000000000000000000000000F524727868A758BB8BA00000000000000000000000000000000000000000000127C792C255B66A76A2D000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001EA2D70D269AD755DDE79DE2C3E2A37241D6B75728CA4541443424FA8CA45DE5D3204494D2E8C2DB1FE9CFF5138C097D9BE52F73150154ECE72FE17861A043E8900038201E907FF8201B9844E6D7810830C986194737EAF14061FE68F04FF4CA8205ACF538555FCC880821CAB0B00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000070B300000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005FDE851B612C6DCBAF2245B6228B05E6008F24F63F07079D67E54019075CDB7C335944C5175845005307D5585447EF4E8A8339423DFCAC2ACB276842FA3A87C600038202A707FF64844E6D7810830ED285941D0913C39ACD43523E2ED36D5EFA5730E2AAF8DA806A761202000000000000000000000000A0A89DB1C899C49F98E6326B764BAFCF167FC2CE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000044176408410000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041000000000000000000000000BBF9DBEFF9381650F99C6D780E4241291F990626000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003A2B7AF76ACFAC5A806E64DFC61FF0C255569B65FBCF65D28EC0D749A6EA4FCF5BB0670F4EC7903B655142EEDD73906BF53154A6AB853E0483B3E6FA27BD998C010382040A07FF82AC5D85E8D4A51000836ACFC0943607E46698D218B3A5CAE44BF381475C0A5E2CA780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000F6D9397093865A569A3B827FBE021B4E00012C140403020401090006050708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000340518E1A8000000000000000000000000000000000000000000000000000000340A6D8E53000000000000000000000000000000000000000000000000000000340CC272FC000000000000000000000000000000000000000000000000000000340CC2AAC7000000000000000000000000000000000000000000000000000000341795E98000000000000000000000000000000000000000000000000000000034201F5F36000000000000000000000000000000000000000000000000000000342433E4800000000000000000000000000000000000000000000000000000003427A306960000000000000000000000000000000000000000000000000000003430415BD20000000000000000000000000000000000000000000000000000003430415BD2000000000000000000000000000000000000000000000000000000000000000412C21886BD0B41CC49A6FD5215CF5296ED800AB1441165EC49509794159F37423A0E63CCD9AEE2E2F9141151A38FC015395A93E7BD1165A70F56E58B4C395EAEAE7BF85FDF7628B4898D35FA780557B4DAEC63350EE2080FE1B0DDFDAD8FC05D41FC79318F8B75D60F3E05925C4F1B0EB2D374065EFEA838AFB01AEB4F85FDBB00000000000000000000000000000000000000000000000000000000000000041A19ED521302CBA45CB3D2BFFBCCCAC9FFE9CBDB523326F3B919B882C8AA6E151F07D3C422D4CE904CE77A4B7CEF971F5AE2CC1F13AF0533D5BBEEB93FF225A24AD3F39415E47A2C59763C8CA92C7A83642C44765125B63F50725E20F201F5B31DF5AEE161CFEB2B393D178C50D2A8AC95DC4084446E7CAF06A8333602E48C4040E3D7B3897DBA6DFF696AF078CF8061EBAFC71BDB3836392E27D0251407AD24380969830A4D3DD476330AB946CD760293E28EFA789DD84E153652D07F99EC4701036C07FF16844E6D781083079B4E94A849344346DDE2D729D6D77FE1F5F7D9B941C8C288054E7D69C5111971002E252C11ACF56D297E445DF1C12538E25F3622E3FE5556D94DE82A5A85BA7D0F228BFDA7B29FE0301A1D55AB295D67D1E53EE478449D0C19A37D1D7E3B19E9CF000381AB07FF830197AA85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014EB00001D5600221D1601D3922A00000000000000000000000000000000000000000000000000000000627BE50F04AA64191075D2296065572BD7ADCB6A322CB0FD3FF8B972991ADB977295256A67B3589D88B6BDCAAD6079C97839E01963B208575784A55EFBBC8209F9738611010382010A07FF82314285174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80D01FD32F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE640C4DC488AE81306BE7F376AACA8F1A6ACCFFB7CAC3D50EF815A7C4FFBAF83885A1C1555BE364B721AB20D53DB314774B2175398DD01C424A7C5E8DE4934E04E21010381A907FF820235844E6D7810830940A694EBBA467ECB6B21239178033189CEAE27CA12EADF80A22CB465000000000000000000000000737EAF14061FE68F04FF4CA8205ACF538555FCC80000000000000000000000000000000000000000000000000000000000000001D6A40DEAE50F850741CDF70B27250D35AFF10351ECFB73D9679BD599BB5E318D23355B783479B6B4DDBF7858EC22B4662A765B52BD093CBD920B832D7F184FB6010381A707FF02844E6D7810830E4FE294FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880A9059CBB000000000000000000000000480507551E5B9B99BA68EBC9030F0E6EB936705B0000000000000000000000000000000000000000000000000000000455E53C1125326DB3A56916CBFA9E0FC452935730D6F61B14F25E938C1496A76BE09664D42EA8663C2AA94B2DCCD0A809C6154D46A2180B9852BAD18F71C619BE5DCDEEC8010381AA07FF8227B485018C5EF280830DBBA0945F3C8D58A01AAD4F875D55E2835D82E12F99723C804C83377C0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000006F06C9F07C3D709EF69BA59E750A1FDEE206DDB2556AC5D071345FF3EE9D9046A6691F8013AFFE2B15F18AA9FB9F72C8285B91B860F584EA93C5A2E0E1611AE02E0C1997E1379B00038201E907FF82017F844E6D7810830C98A594737EAF14061FE68F04FF4CA8205ACF538555FCC880821CAB0B000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000600800000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F49DAC0720895381AF877B2AE20238EF3F1FD8E0AA658FCA2C587CAE3EEBCE07E3580355417FF778DCE4D2A2F2CB5C0FB7DEAB1B505A07E515679A2892B3616010382040A07FF82AC5E85E8D4A51000836ACFC094B61D6E5ECB4188248702F65D59728F607F9E3D2F80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000815FEBAFFB04D8BE4BED76238FDAFC9B000172080108090100060205040307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000010CA44800000000000000000000000000000000000000000000000000000000010D326400000000000000000000000000000000000000000000000000000000010D6FC400000000000000000000000000000000000000000000000000000000010DEA9C00000000000000000000000000000000000000000000000000000000010E1B7300000000000000000000000000000000000000000000000000000000010E1B7300000000000000000000000000000000000000000000000000000000010E39D600000000000000000000000000000000000000000000000000000000010FE44C00000000000000000000000000000000000000000000000000000000010FE44C00000000000000000000000000000000000000000000000000000000010FE498000000000000000000000000000000000000000000000000000000000000000415665049B316E24072186A6F0817D8B1859054B499B9CE9EEA0CEB1F9CABFEB45E211DBD8F88EEE664D7DF24094AD8A4E676DF147F159142A8B668C1074BC55DE8442F329951AAF4683D80AD1416194E6E1FA4B5A667D92AB1CA747BD49DC4F16F7F64AD128DF352299EDEF6D5C9FE9F9031C7E0D5CC28AB45EAD00B3EE6309100000000000000000000000000000000000000000000000000000000000000040C32F1F49BAFF9897612DB2597DEC89A846610D7862A23C48D31C7E3F20DA4FE24F6FABF6C4F819C9258DBFD45A9005CA33BD6A08B2DD6DED8E20C9D998F6A9E0583BA71C8B253C411941DAFBE4120BFAAF1C2691EE0609320B8D2E016E8A79C1FB409E6FB70A7CAC9E7C9F548E7AE501C6F6BA874FF2A8154F71916BF0B59AE24F1009FFA57D58E67D355A703DB3AE2960E3E12B4966ABF10FB682ECCBF5D5C59CF75CBE60505AED5A2541BB6097CBCC30017AA932AF5FDB142A607D25652AD000382010A07FF82314385174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80D01FD32F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE648CF72C822E80E63060F0DDC33D940A52FC46F64E28DF65B24E9AE1CF3720DE9774BAA1638A8433DADF341618DDDFB77BFCCA5FF82E34B065EC5403C56218A121F010381AB07FF830197AB85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014E000001D4600220BBE01D3296600000000000000000000000000000000000000000000000000000000627BE51A9C746FE5E63864C4326C5C9E4E3FAF597A71C3ADF9FA7D7878C20E84D7544CD755087C345C5FA78A7F14DA2EC4BD9177E4268D19E315D6FEB8AAA4BE908516B50182028C07FF12844E6D7810830E25089453BF833A5D6C4DDA888F69C22C88C9F356A41614842DE7924A039FBF10FC000000000000000000000000000000000000000000000000000000000000000B00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000A8457B67136119594321446F70162821ED11343F0000000000000000000000000000000000000000000000000000000285B6569500000000000000000000000000000000000000000000000000000002827BD396000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000014A8457B67136119594321446F70162821ED11343F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000014A8457B67136119594321446F70162821ED11343F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081D216AF0782C98D2EF1C4D942FE5FB6C0DE20BDAADD23A237E138E9D3DC83552DF925F3D797C3CC07A03A79F3EA504A3C5A0F9F0D5F0B6ADC044E3A1F74400B000381A807FF81BB844E6D7810831E848094FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB980A9059CBB000000000000000000000000DF46BD60CBD9FDDC85C1C3985011BBF650DB073900000000000000000000000000000000000000000000000000000000343A281510BE82FB53089753335A0E7DDA407C1D43DAA25157E573523388404D98941A8D7B74BF66A03552DE85C917C7C110F14482C326C18E137C1200870368C1AC7A44000381A907FF8214C0844E6D7810831E848094FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880A9059CBB00000000000000000000000011FD02B172546BE47F80F8F19441C705DA53716900000000000000000000000000000000000000000000000000000007EA8ED400A09351ACF86935A0F3EC06798688AD736A0A1B42E6DB0C1F49A0DE9DE12BD8BD161EBE14F6EC679D93FB26E9A2475017243A6330C1F98674F3AC593B88072A08010382024907FF82063A844E6D7810830F8BB394BA12222222228D8BA445958A75A0704D566BF2C88052BBBE2900000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000C84F245AB3F76CBCB6BDA478325402322DFBB6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C84F245AB3F76CBCB6BDA478325402322DFBB6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000919F3AD500000000000000000000000000000000000000000000000000000000627BE53A996616BDE0CB4974E571F17D31C844DA2BD177F80001000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AA846004DC01B532B63FEAA0B7A0CB0990F19ED90000000000000000000000007D7E4F49A29DDA8B1ECDCF8A8BC85EDCB234E99700000000000000000000000000000000000000000000000000000003A382C1C200000000000000000000000000000000000000000000000000000000000000C000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000251C610C6B640D4A6A181BE407908550E08E7393C3BBB5FEF032864B918161173001397BD4865635B7258800D51D8587643CF51B41AE2B64310E6A8B81C7F30200037D07FF82C5C1845E1CF67A831161E89400000000000B69EC332F49B7C4D2B101F93C3BED806A08104064541216BAFFFEEC8EA535BB71FBC927831D0595C0B23D5C141889EAC119CD7661715FB09D8E6C16A845F551963E4006B97CD1040FE762BC51231FE5BAFE959850F8333CAA4CA166EF9956FEB78A8A3BBA7645C80103820AAB07FF12844E6D7810832792E6941111111254FB6C44BAC0BED2854E76F90643097D807C02520000000000000000000000000026271DFDDBD250014F87F0F302C099D5A798BAB100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB9000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE000000000000000000000000489EE077994B6658EAFA855C308275EAD8097C4A000000000000000000000000948E4A5D2135476EBE533A1E35EDD05A1F0D4F09000000000000000000000000000000000000000000000000000000000155568F0000000000000000000000000000000000000000000000000022E4EAC7B2660000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008A0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000489EE077994B6658EAFA855C308275EAD8097C4A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006493316212000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000026271DFDDBD250014F87F0F302C099D5A798BAB100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000014414284AAB0000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000000400000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000A0000000000000000000000000000000A80000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000242E1A7D4D00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000024432CE0A7C0000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000004400000000000000000000000026271DFDDBD250014F87F0F302C099D5A798BAB100000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A405971224000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004470BDB947000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE00000000000000000000000000000000000000000000000000233F260A5C48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018414284AAB00000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE00000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064D1660F99000000000000000000000000EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE0000000000000000000000001111111254FB6C44BAC0BED2854E76F90643097D00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E26B9977928FB3CA188FFE7396EAF738A9F1550632B2A0C2D5C9FA712622DAECAC29485458CEF0AA91B9B35C99B4A2C95597DBDDEDBF45235D67A871A57A7DC82AEBF996000382012907FF822EEC844E6D7810831E848094146C57ABB43A5B457CD8E109D35AC27057A672E28043C8D33B00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000018EC14C80000000000000000000000000000000000001ED09BEAD87C0378D8E640000000000000000000000000000000000000000000000000000000000000000627BE57E47A89B21D1AFCEBCABB1D291799E6F784E41DE4F8EDE14030F4BB7CCF72C742F3599A3A228DA78F25BC2A39481E8C75ADB182073480351AAF692CE630C6661D6010382040A07FF82AFA785E8D4A51000836ACFC0943C6ABDA21358C15601A3175D8DD66D0C572CC90480C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000B9272C57951E29E59E3027B75D9B26B7000240CB0508040603090002070501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000002123E300000000000000000000000000000000000000000000000000000000002123E30000000000000000000000000000000000000000000000000000000000214010B7C00000000000000000000000000000000000000000000000000000002140E075C0000000000000000000000000000000000000000000000000000000215224BD600000000000000000000000000000000000000000000000000000002159F28A50000000000000000000000000000000000000000000000000000000217150F6B0000000000000000000000000000000000000000000000000000000217A24C5400000000000000000000000000000000000000000000000000000002182A0C12000000000000000000000000000000000000000000000000000000021AB4EF8000000000000000000000000000000000000000000000000000000000000000049FB32F45FD4D3F5932A2B4BB8B89C2EA47D2141A219399E4789E7F456A7B8EE668DC67CB343DBFE399C6057765F85BE559BB19D4BA00372DE9FF7EAAD20C0E32E3DCD4696A8E64F939DE6317FA1F38FDB49BFE20D05A992C65BDABB7B37825A88C24B0605567438C01B330683A391E10CDC71B9A2720F69FD8EA9453EB7054D800000000000000000000000000000000000000000000000000000000000000046C016EC3AF6FF465FAC0602053D3B9D28D8B48A10DD39E84DD31736B9721D0190322D6DCAD89547F6D3FB869078DEC4C711DA100F719F4728523B75D51CF0354403FACAAE796E71B345FDCB1BABBBD4A242EB2D097AF0F739C28F0D491EDA1360A88D5B6C8EE16676EEE2F20BEA46C32D28CF29281B46AC5A14AB67E3542A7B4FE20439D317A69734D58B36BE5824E9F25C7E57224C819C3DDD4E5746D1B2CD34EEA8E18EBC18E680575FAE07E5D973C1F285E5661F822A6904210DB56CE557C010381C907FF82064E844E6D7CE38309EC8F94F4D73326C13A4FC5FD7A064217E12780E9BD62C380D1ABB907000000000000000000000000000000000000000000000000000000000000000D0000000000000000000000000000000000000000000001A6460664E61F17BD880000000000000000000000001BE2655C587C39610751176CE3C6F3C7018D61C1D8F7B59FC1E5819C625DC3AE9544E59FEF33224FDFDB1F7DF31F50A4B830ED0D148B9D2B64B574873CE4B96076FDCD00A6FB3E717F8D993C50C3DBCBA43219A5010381A707FF42844D7C6D00830F34AD94FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B30000000000000000000000003D685292905961E7C5C1CB9327A51314D283874DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD07BE6C71C8EF5670099332B8E66CCFAF777356F1DC7E264BC4A4408D8F20253ABC3D89C19016F9D42BAED40F347DE52C790C22DE9C369436D00F3EE475D8E901036B07FF01844E6D78108307936694768C3C340AA5F0DE946647391FFF30A3D1F5DECF8764011E9B5CDDBC0008FCC20DC9A012B091E4F9093466BA5E2CC5A2E045BCBE1C0C3F8A973782F6373886691DFAA4AF2CCDAD82C1923C14538E02A1B2CBB45BE7B68D44D5D3365B40000382012907FF820A9B844D7C6D00830B929694737EAF14061FE68F04FF4CA8205ACF538555FCC88070E4194500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000587E000000000000000000000000000000000000000000000000000000000000587F00000000000000000000000000000000000000000000000000000000000073F1000000000000000000000000000000000000000000000000000000000000776938658B3857A2E616F2A2FDF4B98FC914FC5F02A4FDFEDFC9D83B65672447E60D6445B126437C1B126385531D43BF3B687363932CCF9102BBF4A7ED4057675FDA010381A707FF1E844E6D78108309E9C494FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000E22D2BEDB3ECA35E6397E0C6D62857094AA26F52FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF56375748716FAD259458609450A2C8E06F70AE0CE132B2C545EF10F895009B7C6FA84C02625D9A8C54A4E60279C38355D74B8542C3C05F8AF82652B99884E66A00038202A707FF0B844E6D7810831278109468B3465833FB72A70ECDF485E0E4C7BD8665FC45805AE401DC00000000000000000000000000000000000000000000000000000000627BE625000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000E404E45AAF000000000000000000000000FC5A1A6EB076A2C7AD06ED22C90D7E710E35AD0A00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB10000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000005C283D410394100000000000000000000000000000000000000000000000000000F546CE1511821454000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404B7C000000000000000000000000000000000000000000000000F546CE151182145400000000000000000000000048766D191E4F0A0A4BB1514AB2C43C02B26E22D300000000000000000000000000000000000000000000000000000000A54A5735240C21A88C3F04E488BBD7E5D784937038DFEBCB4338B208F6B1AE3761EEFAC2E7AF1CE6EEB53CC639C1426E5E7D9766F91857CA82D13C26F429ECDD000382040A07FF82AC5F85E8D4A51000836ACFC094CF17B68A40F10D3DCEEDD9A092F1DF331CE3D9DA80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000084A93CB8E980AC7C60290BBB47DDA3AA00009FBD0301080603000709050402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000C486BA5600000000000000000000000000000000000000000000000000000000C4AEC37700000000000000000000000000000000000000000000000000000000C4D4563E00000000000000000000000000000000000000000000000000000000C4F9D24F00000000000000000000000000000000000000000000000000000000C513E66400000000000000000000000000000000000000000000000000000000C513E66400000000000000000000000000000000000000000000000000000000C513E66400000000000000000000000000000000000000000000000000000000C521F22600000000000000000000000000000000000000000000000000000000C591675C00000000000000000000000000000000000000000000000000000000C7BCAEC30000000000000000000000000000000000000000000000000000000000000004CF3D7E08422CF2AE8C985D1A0D053AEC1370B6568E9A547F528AA82CE94085238409851E77E50AE69A72F1BB9BFD631D189DF65A02748BBF0B6246B35ACB6BFAB762977C264FDAE158CA3E5D1160AD1A7C8F422ECD39F1F3DF6B95773D7222464742D2A6DCB29A74E138D2B9368C8BF3891EAE1F0CAD94740BE803016997E91700000000000000000000000000000000000000000000000000000000000000047A9FE9AFE21758B114574F7298F1AD50473B6B43A60AEF90AA441E0ADE578E277F496217699FE6AA1E8429FE757D55028F518F3F6CA9B5E7A387D57EF7D86653632D9E9165883A78C97D36B0B63EB7F911B0CF71832DFE67D55A238B6B137E037C40F7A6F9C9844F12D8901F30C2101A72F0EC4D04CA0FFA0EFE675F41A33A6FE273214FB8E92CA7E71E43CDD58FC1B4FA8C7419D33A746BFD2D2C3DB9281FB224A62AA5E7792F1EE1A276F60FC7C25153517B36F9652DB91A1B850AD6F0BE3C0103820C4707FF25844E6D7810838A565094ED67D6682DC88E06C66E188027CA883455AFDADA808766C48900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000007186F67723CA2570828C29519128E212E50E8202505BE8A8A113CC421E1EFBA6402E63738235029335AC3AB789243D1302EBD762FAD49CEB932A784C9905760E8384029125C7F2B66E242A28EE79FB596CB538F52B57B85B92DE7EAFC5134BF5F16EADFBE8B406CC4A30498A9886C6FD06BB55CCDB9B7CC0D7B5C19803B92EE9001CF2E8DF85DF432A520F72318CA792DC5EA565D803F792FCD439DEEB366B71B0D6CB60AF0A95BA14C7642C5D99837D82802A8189B1436594A5D5D7A6E3F421B1E6B6DC3FEA990CF4C97ED247D499586F9DAE4EB4AFF4DC97CA77916BBD058D825319E95C7A88C841D413E0BFAE0A95AF0E56768FCDD71560B5AA1EBA48CB0B83959EE4913C176FFD4BFE9D3FD7D2C15F275004EBD59E0FD5920637629F7583050E5F43A547FCFA2F97269CBB0F6878792079E87158BB477E9CC2F8DA4E6AA770A10D670B40073031EACA36E7DBEB85BA1902AA969B37FC11B1A1B6E922E21E40560C0D22D11898DBC98DC5268169607B5F7AC681FF919FA542733F70227A1A121B7E21469AB214FC7CAB75233CC20C27E4238FE62CEB941334CF37D32CA1DAC33282FE1A553E74A1895F5C898936F9134C83181EBEB68D528D5F9255053CE031F24237B0535974FCF2396EC1C1F138201D8225C4FF50C0A867D95D95A80638F16DB109CBBB63000E92BE86E8E2B9C0FBCCD358885B764322E3F3BFCC9F0472F2DF793FE91B7AA1935E69C83A55C8B28ACC2B8E57BE24327C4F400311C521D242E8EE79082FCC89FC27BF8C05F9CA5FCAC0AB982265F7603103FB36DA7D3AC912B0061A73DCBFDBDDCC64F438D0F1AAC1A508F36C7CFDCDDF41B01FAD89FC71A2E0E9E3C751670198B675CEFDCE3A06DE0EB4A046EF6283C64CE66C6A153D6601A8D9EBA83DFB01DE1A940BF310C9D1F1C8B20E82D0B6E7D6549A71CE644BC6F29CB6E6B628E44FC57F297E1AB4C0A559383CFFA31ED72F073AFF6D9C3D8AB610CC34DA213F89C9709496907B77D0EF3441AEF350A7166C95834ABB8ACC998C51062A9301EAD2CAEAD65242F52BC1E39FB5D4E82F7882685B242A2649F6F7043155DCEA6F60748F8A4F451FACE7752E76D48714654042DCDC42E6CD9ADDE11A50C91F0BD31783B7897BB7893E579C6B125D7A71BFDB8F2BAE5F479BDC72E29FB0FE963C786D18B83F9C74C21DA41BCD6587D3CC562EAB6CCB6CA41E53B55A75D00F67AAC3AC67E69B6D47CD45C3B79ACB83B07D27F936203F4722FC58E1384462844D962DFCD7ECA8543C07634876D3B9035C25AC708C6FF06DCE7559C8A1A381F305F0FF74A60E545C6426D26DC3A3349FE6F4B1D05B559C0FDC0E86D2310A241EF20F5A0B5CB7F6500C700C8F6436DEC435E85EFFDF9FD04C36F211A82A7CA2BB376E05E50588160EA0C9DB447443756FD1C2BD5C46FEC8E0DAE121BF0CACF0932FCBBAE808289EB138EA95AAC2E7D803A12BA0FF9DA5A6753785FC4FEBAF5179A85658BA0F7BFABE3C0B5CC26AC3A508D6D0C23C77D712310594F749003790FB6A5F9903BE17317AB887D7AAD27617405AF5B0F24C37607166E792E1302E91CB19F044316C9A61EA893D188D8E5E703DAEAC9D28EA96CBAD4FC8247CFCDA80D6E6B38913F9810345D37A6F13A3CE9A116F35894B08C2D7B9B2B442161E97B1AB03E853F5C528BC2ED26F77BF739135AEBEE5F5F7DA048C1C33CC834F9B16018ADCC5B56FEEAC355FF146D84A470520C89380BE3BB254E412B18C4178CB5BA1E2F7773D2FD6C57CE0FC316006EE7DF6CF3220BAF69B460D98BF463F8B63DD4228E3AD7EFE8B77FB5521ABB88525B9967822B058C7C66A97F24A672F9D71543351D9678ADC617851D5D7BD88315020E9B3820D9CB1CEE46D71699633617FE033B4B8A5F24C05CAC000B373414B23BA719BC899A9A47AF4B1C644852253088FD1631AAC347AFBADA4D83555297B3720FD95D5FB38BDB6D0F691D7AACB8827893189DFF2EE4205CF3F4ACE0179C8485216252B603013DD6C51E8F2111F5E7D7F430617769218FCCDAF3F3D6D651BF05318C01C8866981ECA9CEBBD6BEDA08F0CA227D11DB4FC403A8E9D588A5CA97EE188D2341B9B6373D1A7B20F6A57B3F964B23AC9F5D6E672D301F4E47D34A687C37574A282AA428E6EF2809B495DEE07D461F7D698CC7883EE9A7DBC73612EFCE024BD3DA324A255A8CAF2FFEA2C3086C2117FE18ED5B11E14BB6E27F589D997AD02C593482BD1B41FD3A7553C4DC1A85262F0FC2AEDEB60FAA35D08CAA9B1F19DF2860444800EB8039D4AC8C0D8841D22D5301F5A4C6F7EE9DC6684DA89583457AAD3D641665FF46A76DFAA517066D34261CE86E5434068CFA7C8B9B95E17D8951160109B2A83BA22A5E2CCCC81574C43B3CCEC9985D2EB19BF39833A0169126FF8D72BFE5C52E34DA1227CC1BDA7BA1B4339C080A5D839C1928192FDBF30332C6DB68413C312FEEE275FFBF3EEE47CC89203328B9E1296E6C4B8133E866762BFEA61473D0BAB2BA7FC75407B4383A990C18815DB050D6D04214CC4C48FB47B863202C0E5F61BBAFD9D94E638F6EA3F1931833F9DC7C96EB69387401B893F700511D8DF02D9AE41457670B66C15719E38401FBB4971B919EC235F13151D9E92B0F8E54F9F92D260DF7A953F92850F2242F19F437DBB442625CFBCCD13A8F99B6F77FDC0559EA0482CFB5436F8BB3EC5036301D0DCE5EC7C9380991314996E05FDB7F1D3ABBCB048D6CA78FC1984EDFBEC419D6758B2279C1E03CF1E61DBDF36AA0E6458A93437AADFAB43502D35FEE1AC64B18099AC695E57524C337D1718BF266A4DDD6536BA4EB6AEE2E2A1A9D44696743E1645C396E06E842555DC778AF02F62E641617A3131385E52866AB243981B130A8A02CF98A817F84B713C7C09C210FF84896047EF5224DE7B3EE4C5EEE0F2A286EBF63727CC984FE075319C5AE054541A5E3BA5144A048A6A7A6CA6C5C5B7E14EEE844C113D644938C85B148CDCF603284BB2AE77FD646589A917C71CDDDFF24043E07B096D9EA62C8C839923F9AD21D229D4961BE98AE50F0887451031C752A0314D9194DB63F432EDBE14F074F04FBF227214C2BA57B797AA47C69434A011CFFCA6EC50063561EFD961BD1F87F2EDBF711FA451E6B5343113C1D3633001B2446ADD528AA65924B78CCFEA095EB51025480F26D4E8CCAD9DEB719FF40E47B0DBE1D6497E688867B268B4747A5EDB7475A0B28E6308C38C149D9141914909520398FAA6E0A8A83A5CCB9028B5CB82C96A61FA7D0461867C9328DCF916F0FD41AA843CBFA9BB4AFAB04F3C041E8522C6931E6FB1438ABCA8C2494E712144F353134F7F51365903EDBDE9221E6808000E458D719B551C7A4F12CF0F9B0B156801A3D09677960A976942959665DBB58C1B5B6CD2D6E9B0C01F8C3B45BE0C20F4E10DB306C85D098EB8A5C4D566E3597FDC9331646BAA490E2DBF4AEBC4245A3F8000000000000000000000000000000000000000000000000000000000000000724057A3943DDB9982CC0AF78FC688AF305316B8EC0AE443AC4D9496E2E03A63B1AB50ADF7F50B4710194AF8676E9CFFAD670D48A50230BCF1F69F201DC7EAEA910F92CD689035D3D3C7B6B1DC7FF05FAC977F10C161AB8CDFDB511AB569013E42E5297D50C20F2134AC4C59D75DFDD4B99B89F14AF72CBF96B165DE731D0C54A0D2C1D6406AD61C8C25548F9B5412747091CBD48AFA9C99BA7ABA8C13BA96BF91786E8CB55A31763FE99A09D7A36F8783F489F3EBD52B74275CCD8D1E01624AA0BECCADBBBEB3D20D127CD333DF6966C0BFD4EC1C7F09828CEC68FD07FB0D390191C583D75CE6BAE577F199FC7EB2C38AE565AD80AA8F11BBC9659EE1DE0A66A0D648128C3A778E7ED0246AB4DA1EA29AC00E690B98D31AC33CCFC3E4DF5DC782FD76F0472F79527F15B84B15648AF306C98F8A204052171B2805139E0B4FD81281BA623A6D1D606A9E595540590776D31763C390EA0733D58CE521B5362B28E2EF848590E2D28774418449C0327206BFE3F42233C99EDCAF5536535268742302DF442614B0DA843AB16A3F67DCED8B788BDA75337343D2B675EFAC1C196203E0F132FA3160476C31BBA64350BA4959B87DA3C887EC6E60C9CF307753B84837E6DB9DCCF21E336232F402B5CB0AE5E4D8FDEAE8CF81F3D0E169387AB2E6B58F75DB6D9D802B6BDDAA86705DDBAF81653661407E3A5597E650C91CB9A471FAAD700036907FF80844E6D78108307A12094A60113F7D43130919802B0863ABDCDB956664FD5855AA698FFF806F5BC2CE220A57B4B41B50D2AA9FFC1B582241208FCCCEEDCD748CDFD174E6B856873936AAA6DA228A5445C4A1FB7E14695308763101220D1358196970234CA0F01038201A707FF10844E6D78108315CBBF9474E87FBA6C4BCD17FE5F14D73F590ED3C13E821B805B661039000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000081090797753F24298047AECEB599D92514FA8CA4B173B0906597320E3B4AAE154273AFB0294CA87B4EFEEADBF49C6EE85FB821614EBE1EA6EDCF9189FF17B5BA4350719FB19B707141FA3108F91F0107A558CFF72D320442D42EFF41095FBC03CFB5081F481FF68D9FCADFA4AE163BAA90B5E2EDC4ADE7608DEDAB8A09E1B6382894D7425177FCF525C18DE7E0966C84FEAAB4F66A313F4A69542E697CC17262E8BAF897A6D1ECF1E79C778E4A5555A9ED5E86575BDABC911CBAFFCAFA26163A8548F7FD286020C4254D382CB88AF5D890A7229EC1784D4097EF6662D804C9087BDEAF1BC6B46D2C4E6F41C39C3DD1C5B89353478A8624C0BBB1384EE2A1338AD4AC65AF43083C508C9E71C49CED76D2BC6B49041923CBC57CBF0CDFE53EBD3864F632B8487D19C219B0443DECC62EB50426ABAA46BDF6494C216DF3336FECD8D000382040A07FF82AFD585E8D4A51000836ACFC0942F45A77C5024EB546E9E7F445F266C0D3E71E61680C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000E2B45FCF3F7E0DDD1B2470F60F3A1F64000008EB0606030904020800010507000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000376B9F400000000000000000000000000000000000000000000000000000000037764DA000000000000000000000000000000000000000000000000000000000377F7560000000000000000000000000000000000000000000000000000000003785D4D5000000000000000000000000000000000000000000000000000000003791E52E0000000000000000000000000000000000000000000000000000000037B387870000000000000000000000000000000000000000000000000000000037EF47EB000000000000000000000000000000000000000000000000000000003813FF31000000000000000000000000000000000000000000000000000000003813FF310000000000000000000000000000000000000000000000000000000038EC24C00000000000000000000000000000000000000000000000000000000000000004EA110508BE55738059AE9E345B2F435E5F8E4842F4879179C8F268508C44342899FBBAB291305D8622C5360E71CBB45369F9B95D4B0FF06B39B266CB478C02F338196F99DA1F517DEEBD7A35F0B50FF03771FEB6D31B7787982127EFE77B375DFCF822A6504A41CAF1E06523852BD74CDD595D5D25FDE2F21B8C5586A4674245000000000000000000000000000000000000000000000000000000000000000426485945EEC2A91ED211E49E31E786140C35246AA34538C31D8047F2AEF7BBC2719221C2D4F739F96DF160B60E485ABD7BA82C9CF6083F8E479CD097D091EE72623F06D140953014DFF570CE2D9022FF7117ED8E0912DF0C46CE8D8911BF4CC102EE1AECD32BDE25F4B751D805FC0E7F19FBD3AB8077478AD6CED99B2C3AC3D96886371A91B5D6B053F562C51AAFBA1481F3546FB656A167D1629BA89C79F7D72D9BB76F1E29BB4B37A6126B096D542AA11FDFDFFACF336D19DF7603DA1E79AE010381A707FF38844E6D781083092F5A948EC75BC963181489D7FC1D892F687B8B0987D9EC80A22CB465000000000000000000000000282619DB98F8A43E98065F5B306AE740D6D87A8400000000000000000000000000000000000000000000000000000000000000010470E7BF3B8D12BF06F4B08EB7647AB6FE0AB86F4BFB98E7659EBC7DF04ABA3564D3CE820201748F6D33E91FBC47E415E46AD570A9F206AA3B210ECB4245144A000382040A07FF82AC6085E8D4A51000836ACFC0943607E46698D218B3A5CAE44BF381475C0A5E2CA780C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000F6D9397093865A569A3B827FBE021B4E00012C140509030401020700050806000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000033EFE38F00000000000000000000000000000000000000000000000000000000340CAD8DC0000000000000000000000000000000000000000000000000000000340CC272FC000000000000000000000000000000000000000000000000000000340CC5179A000000000000000000000000000000000000000000000000000000340CC5179A00000000000000000000000000000000000000000000000000000034145FB459000000000000000000000000000000000000000000000000000000341C4B5B400000000000000000000000000000000000000000000000000000003427A306960000000000000000000000000000000000000000000000000000003430415BD2000000000000000000000000000000000000000000000000000000343F69F02F0000000000000000000000000000000000000000000000000000000000000004E597BD20AE89D58F6E989502490896FD7CD22A1E10C63C598AF7729B52F868E1E118A9F8211AC9405FD2F74A2908E4343088A6B8AF85275DD72522DF471015116FD40C53BDF51AB662A1468DFD886DAED61C9EAFCA4AC948FADA8BEDBB374BCA7FBF8218429FACC7815FC9B33CA3584BD162DFB5C3904141C769DE8A9BD1AD44000000000000000000000000000000000000000000000000000000000000000471599B6F48333ED9DD5678625A878D01852FD8E3CC6FC4396C2BAA8FDFB4FE2655CAF19E8EA2551E3620B62BB09B451D6D8E333D5B71AB18C32D03E2E48433F6758628132742471FBC4265334ADDC011F24BE5C3D16EA2254079A55D2922CB2069398B51F5742A7270CC95593A70ACCF90BE43E9136402D3F89C1BAA43C72861891FE74819B72AE66ADDEF7A7C0C7D87E02C10DACB5F1EAB555506FF9DA077DC48BC7DFCE59E17721DC3375ACE832D641CC576CA2CB6EDB6FF6953F1EC4123AA00038202E907FF8206F7844E6D78108315FF6994BA12222222228D8BA445958A75A0704D566BF2C880B95CAC289811B1EDC7CF26E626EC94074693526A7EC80E8500020000000000000000007C000000000000000000000000FB59B91646CD0890F3E5343384FEB746989B66C7000000000000000000000000FB59B91646CD0890F3E5343384FEB746989B66C70000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000A72159FC390F0E3C6D415E658264C7C4051E9B87000000000000000000000000DA10009CBD5D07DD0CECC66161FC93D7C9000DA100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000DE0B6B3A764000000000000000000000000000000000000000000000000000002C68AF0BB14000000000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000DE0B6B3A764000000000000000000000000000000000000000000000000000002C68AF0BB140000EEA4A9751F569F829F8DA6D35680439F8FEEB54E64F876F9A684A6B736F3A4427407F1DB35A29B16EBAE97ADD1DE8CB4FB7131EFD85FA5435FAEACCE9B4EC836010382040A07FF82A4FE85E8D4A51000836ACFC094660E7AF290F540205A84DCCC1F40D0269FC936F580C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000780D2CAE604EE917F49DA87156E8EFBC0001E7600604000706010802030509000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000012BE2AA19300000000000000000000000000000000000000000000000000000012BED7AD5CC0000000000000000000000000000000000000000000000000000012C257D16460000000000000000000000000000000000000000000000000000012C39BEE2C00000000000000000000000000000000000000000000000000000012C39BEE2C00000000000000000000000000000000000000000000000000000012CA76B0EC00000000000000000000000000000000000000000000000000000012CD6C5891A0000000000000000000000000000000000000000000000000000012D0F9BED740000000000000000000000000000000000000000000000000000012ECDA0F0800000000000000000000000000000000000000000000000000000012ECDA0F080000000000000000000000000000000000000000000000000000000000000000452900DF739455DA39CBECFDE8DC777506207F7A19A9567C57B4836B98D6D3E849DA3C628B40ACCDD8D483B69564E52024675BCD6F0160E0F4B991A250553BB313095785587210D4DE8FFEA89F38CDD54DD04BB2DFBAEAD6BDDD3E1D90E522EC57BDE43D30955B421DA61C76A4C38FB69B57FDAEF2EF02084A349C4798E3BA31500000000000000000000000000000000000000000000000000000000000000045A0644C72ED204EE195DEDDD625C507B0C7AD222628F98231F7E3DD7F3F37C405974485A0BFBE5CAD344A867B45CD0FB366D19E25A2FD0EAEBAE25F72FA9E4974D91DFF010DBE0B63330FF0F9F2FEDD1711730CBA4C04C075F415E69848685503E5121A32C36ED61CB84A06F9123D3447FA6D4E27E9CB14CCAB41C09660A38DA981AD234F8A3BB62AC2141B1A7AC9CB0C1CDB5ED6EF7E1FDEA56C0944F4819685550CC1E1061B5834573DE35E3BA483CA903745B8C9B2D1EC27E944FE7B19625010382028A07FF822617850BA43B740C830F487794BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000218761A6D957D975BE472E0680EA45ADEF03CFB000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000104627DD56A000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000A4394747C5000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004563918244F400000000000000000000000000000000000000000000000000000000000298E7797E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005E2099E0FAA4C794C92D635B092722CC18E7FD5965C6C5DFA56EB3BE205358935B95A7D18B538256F500664D1FBEBCFE13E597A98C178DDDEF09034B68BF2E15010382010A07FF82314485174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80D01FD32F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F40000000000000000000000000000000000000000000000000B9684137373800000000000000000000000000000000000000000000000000000000000627BE65D79361DAEC4BA745441139023B8D7BAF052EB041C6EFA3EE1E9D7BFCEE69CB56928BD31A67B04895723DEC4CBEB4601083B7A5F181AEA117C98700D243F671C58000382040A07FF828F3485E8D4A51000836ACFC0949B8DDCF800A7BFCDEBAD6D65514DE59160A2C9CC80C9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000017E1DE687DF661FD3F7EEB0D2CD65F500000B5760302010607080403050009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000002CB14D5C000000000000000000000000000000000000000000000000000000002CB18615000000000000000000000000000000000000000000000000000000002CBD3CFD000000000000000000000000000000000000000000000000000000002CBEC5E0000000000000000000000000000000000000000000000000000000002CC2C309000000000000000000000000000000000000000000000000000000002CC54909000000000000000000000000000000000000000000000000000000002CDCFD7C000000000000000000000000000000000000000000000000000000002CEB1623000000000000000000000000000000000000000000000000000000002D2E2980000000000000000000000000000000000000000000000000000000002D2E29800000000000000000000000000000000000000000000000000000000000000004786D145292308F5D0E5B539BD3D2378BFC6D4FD913D113CC97098A10651D35B2FC95DC1843FA7B456BF7921CFFC5BE0C152585FA178004F25D5E7B46809E1B7C7AFF283015090D61710437D8F301B8DE1BAD3E4C79599ED595363DD3D38DE30C2900D95653D20A78571CE6F24163B9FD6058407A830F80227F06C4C76CF9DBA5000000000000000000000000000000000000000000000000000000000000000444469C0F8E23D6031541A9CA2D51931C8CD8F9BC4B961BDA4D8D42E71FB761E727013A5B082F52AF13D87A03F919BE71CD109D356D47BF9E8A1A9B7B37A3676D000FD137C37A88F79A53E06234FC9F01B653AEF0EAF6A5711B9E3CB3C8C22E830AD3024EFC0BAD2569EB0A2B6CBEE90BC30597CA2AE52E6EA3059C26A5C823214132AC97D09B51D62C8244DFB871619A3FC7265AF9806C39F2234107FDED47485FE1DBB59137A486A763F8969D7EEB6687D2D5B16AD152905EF655E32F611AF2010382046807FF81D4844E6D7810831839C894BA12222222228D8BA445958A75A0704D566BF2C880945BCEC9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000C5937E880B21560157E3A5C9E6F90A77005AB04C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C5937E880B21560157E3A5C9E6F90A77005AB04C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100C61FF48F94D801C1CEFACE0289085197B5EC44F000020000000000000000004D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000044AEE83BD82225AA7900000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000064541216BAFFFEEC8EA535BB71FBC927831D059500010000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000A684CD057951541187F288294A1E1C2646AA2D2400000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000044AEE83BD82225AA790000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDBE034FA049C506801336A37B0C4F2EDA3BB4D004F9770F6528554FD89DBADE5C5037B8266292EB5721065B9A8736D04725833398FC65F6C408AA34663837E5EEB573572010381C807FF819D844E6D781083086BCB94DA3CAD5E4F40062CECA6C1B979766BC0BAED8E3380AC99CCB6000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000002D6ADC1F4A0A58DA493B0B342176EFD257E0F5998C30D0D1BD64FF43592A6FE28DC723EA4C6BCAE554CE8ACEEE4DA822CA046C8848EC85F265BE5D84B7AB7BD1BD1600038202E807FF57846208D614831229F0946FCE1A7C3347E78D22C278EB3A5C72EC8FCEA29404111E9A2E920000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046C0FE865545353311D61E247201A1DE3CA0E62E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FD6F388945D27E6B2FAA9CFA03D5ABAF3EC8C111000000000000000000000000FD6F388945D27E6B2FAA9CFA03D5ABAF3EC8C1110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8000000000000000000000000000000000000000000000000058D15E176280000000000000000000000000000000000000000000000000000058D15E1762800000000000000000000000000000000000000000000000000000000000034ED1AA8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000627BE54F00000000000000000000000000000000000000000000000000000180B3F723680067616E64616C6674686562726F776E67786D786E69001155903B67929D000000000000000000000000000000000000000000000000000000000000000001E0000000000000000000000000000000000000000000000000000000000000004183EDD4306202A5C30F93C8E7C83798CAE85602E182588C6BBA0975556D8490892F23D02772B46E3E9ADE0DBF73A74C0F105A436B4B4ABDD06F5718E9460B8A211B000000000000000000000000000000000000000000000000000000000000000CD45CB5E905800BDF0B8B786690887CDF5758B262E8F75E8D2D004176FB63C2103F3E1A29E79ED3C6A7AF179E07EDE4DAF0C3719F01872EC84A3BA2ACAA90DD000382016907FF8205D084570DFD96830E244994F8D88D63ED3A2104E664AE8715FC9F80ABBA864D80ED7437080000000000000000000000001B02DA8CB0D097EB8D57A175B88C7D8B4799750600000000000000000000000000000000000000000000000009B6E64A8EC60000000000000000000000000000000000000000000000000000000000005D1EBAD800000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000627BE543000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FD086BC7CD5C481DCC9C85EBE478A1C0B69FCBB98F116DF8F3EA0B1BD1E9C4A1AFA090272D3E3ECC9DC2D453AFF8BBEA27E06BAD393BA6DFBFB170F5A45E819A415ADDBBF533D7E633E611B964A1B837CEE5C4B3000381A707FF19844E6D78108309E9CC94FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B30000000000000000000000001111111254FB6C44BAC0BED2854E76F90643097DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C88F69EFDAEB5D8CD58F4BB7D5A98F2047BC3251D6CD19E59DF14E63D2F41D87F3A0444CB3AE688D0647CDDCDE6BC2A43327AD073C0B834A80A7FD50102ACF1000382010907FF820234844E6D7810830BF11694737EAF14061FE68F04FF4CA8205ACF538555FCC8800A0E28D4000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000AF600000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000006AC16CFD0977A5B26C3FFF5BC07D88F76795F58B15D377728D8154A3B99E0F7312611C3C9E0E99E5F486F059D44E43384C50FB3FC06ADF754215C6208292115EF76F0103818807FF81BC844E6D781083088B0C94602E50ED10A90D324B35930EC0F8E5D3B28CD50980049878F3000000000000000000000000000000000000000000000000000000000000218C159F5227D12B3477244FB16C4C75362F7E302D2C7CA03525801638E303C7F6471C9C5599661A943F82BD1EF141BB29A8E6ED54BB5E4F064CCA29B64EEF94822C010381E907FF820143844E6D781083098D6394BED32937D8A5D1421241F52809908F1A17D75BDB80FDE2832F4554482D5553440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000001F78A43506021458030F6B47211D520CA8E30ACAF578D03410B6A08276F65824E8F23C9D75DB46580730D6FCF65D607E6D294FE42585C119CB0CA8EBD9E1CDAADCAA149F010381AB07FF830197AC85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014D300001D440022001001D23B7800000000000000000000000000000000000000000000000000000000627BE534F9D73590705C2E9ABD672865157AF5BCB269DC5A76693AEE894ED2E3F023DA0B17AE2FAC713AFD1649881726D6657BDE63BD05DC2E82126313F7EF10CF00D16B000382012907FF822EED844E6D7810831E848094146C57ABB43A5B457CD8E109D35AC27057A672E28043C8D33B00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000018E1973C0000000000000000000000000000000000001ED09BEAD87C0378D8E640000000000000000000000000000000000000000000000000000000000000000627BE596FFDC83047DC064B96D78A71EF71D489D83A911E3EFC9D0B7DA17DBA9F802E0E67C7328EC40264E966EFD7F48F237D44A00DB9FE713B80E44591EC1ADAFCC593F000382010907FF8202F3844E6D7810830A898594BED32937D8A5D1421241F52809908F1A17D75BDB8039C6E45D4554482D55534400000000000000000000000000000000000000000000000000000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000746A528800000000000000000000000000000000000000000000000000000016BCC41E90006A95F4353925C31DD60F1F2D7D4C64948D5CEF1D71B8D51C14830D2216C9B9483739E59319F3F44E12114889CEB4626E1FC8A520F303FE50DFD85680DF21D7810103818907FF8238948447868C0B830B3B0094148516DBEE924DAC6DF4FB040234EB1DE19B251D8074A1D2EA0100020300000000031668614A02F46100000000000000001D9332950000000041DE14C09F1B4A9970651624B0D2F408C64A2B989E03B5FB43B154753E2AFBB168C5800E942AF1B4B0029CB636826400BF55CFA20AE3EE385C059D4151C0426B01038202EA07FF82094F850BA43B740C832DC6C094BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000FAF5418E03D052F8676C30115D5CCAE81C52BDA000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000164627DD56A00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000104414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000BB8000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F600000000000000000000000000000000000000000000000000000000627BE7910000000000000000000000000000000000000000000000004563918244F400000000000000000000000000000000000000000000000000000000000297644E16000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009A84D3C724E20C69F106AB7103FE2F47D7A50B7B3E2FA5499E3C4CE2EFE8AD5C09E5610F2761ECD46E237044332748867479D0B6D9602AAF09B7FE34CF721FE201038202EA07FF822B83850BA43B740C830FB0D994BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006FD9D63FA34644454808E188956191AB016F1806000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000164627DD56A0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010438ED17390000000000000000000000000000000000000000000000004563918244F400000000000000000000000000000000000000000000000000000000000296E911A100000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F600000000000000000000000000000000000000000000000000000000627BE791000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033F11E0750B93E4117C076FC0EE92BF2180AA6E67518B6777CA4CE7202D830A4BBFA833EF774B158969F06FE2A9CB06CD75DFB05C039DFD278D115F31CD9681018202EA07FF821AAA850BA43B740C832DC6C094BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000FAF5418E03D052F8676C30115D5CCAE81C52BDA000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000164627DD56A00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000104414BF38900000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F4000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F600000000000000000000000000000000000000000000000000000000627BE7910000000000000000000000000000000000000000000000004563918244F40000000000000000000000000000000000000000000000000000000000029739D11A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003A3D6C74E7D964CF2FD427E9B2AF47617F70B18B5BC0BF945BD5244C339F76FF2857753AC717D51EC9842DC6D2776D8E37175E9F453107669D2569BB8843E159000382018907FF82013D847347B093831E84809420278D3707B3FC50F856FEC90CF10228D61A39B880743ACB80000000000000000000000000905DFCD5649217C42684F23958568E533C711AA3000000000000000000000000000000000000000000000000573BA5CBE126800000000000000000000000000000000000000000000000000000000003417DE47800000000000000000000000000000000000000000000000000000000000000C000000000000000000000000000000000000000000000000000000000000026F2000000000000000000000000000000000000000000000000000000003C4F0F7C000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC8986F97BB9E8544BB1B09CD66CE624E9DC4C9A147EC5C1C7CEB3278C8F114BA495C56A5E6350849BA31F6C4D434EC065804447291D12EA7C16EC606B9BACE5F07010382014D07FF82061C85012A05F200832DC6C0941B02DA8CB0D097EB8D57A175B88C7D8B47997506829B690E7FF36AB50000000000000000000000000000000000000000000001B4E5A9019BA61000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000526724C61422C5AF9423E32D8236AF8A715805C100000000000000000000000000000000000000000000000000000000627BE603000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FEA7A6A0B346362BF88A9E4A88416B77A57D6C2A3B8C637ECA90BC30C08203FDA3BE51C2A59F3C85FE8D0DB06E7B365F79E3C791745DEF7CFC22CD1FCF1797B2C518869286DE8994CCD94418AD1373CE1C3C12A9000382014D07FF8203B385012A05F200832DC6C0941B02DA8CB0D097EB8D57A175B88C7D8B479975068274C00E7FF36AB500000000000000000000000000000000000000000000014836B3050CA820000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000003E9F3BAC431F8B00BFBDE5819B41330DE0A46EF400000000000000000000000000000000000000000000000000000000627BE9EB000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FEA7A6A0B346362BF88A9E4A88416B77A57D6C2A9C826ADD0CAC437B64DC54F7888470010DACC6ABEFECA4C9E5C2711D35AD36F1698047B1332B606E87EADB6A50B480A2010FBA9B9F0C0A87F5878C644B153C9C00036B07FF0E844E6D78108307936694CDDF1B4A946C356F23E953DD73B1BEED45F535BA87A6C69AFF7CCD1B00AE12CFD41A51C2A3A0FC2139F220D8808566776EF941EEC6E12FCE098B529181431661CD84010D289AF12F107E2F61EF7399426F649BBD697D61B7346C161C8E010381AB07FF830197AD85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014D300001D240021FC6401D1FCF800000000000000000000000000000000000000000000000000000000627BE53AD9E9797CD2C9F1DA3A1EC6090BAA3332DCD16903B7AEAFCB7521796B9827BD847CC22DD880E4E36D60F086DDB291E653967B7556C9A9B2D3F349B1D0775181C300036907FF02850218711A00830C3500940938C63109801EE4243A487AB84DFFA2BBA4589E84052FBF420BF93D242CC920A81C348A64CE7C432D79F9D55DDBE4BFDF34906FBB67C54887DB128CC413DA9EF1FD71593AB4A2D1A678E7A689CE71E00EE7F92BC90F023049A500036907FF82C5C2845E1CF67A83111AA69400000000000B69EC332F49B7C4D2B101F93C3BED80A7104A04DA17647161E19D30B414D82475778814AE945CBE886EE3C2A8EA01B7E9451AD46F7B6929BEED81097EBCDB381C982CB308D72CA0E31AFCB2DA37A3FBCD2F651D010382012907FF82A6AF846208D614831165F3943749C4F034022C39ECAFFABA182555D4508CACCC803D12A85A000000000000000000000000ED22B30DDCCA30413CF886ECF4D6EF5BED2A7965000000000000000000000000000000000000000000000000016C815AD3AE90C0CC9C44C554598102B30A4A35D857000D95761A2509603FDBA8E15C2BAD8996EB000000000000000000000000000000000000000000000000000339C62E51368B0000000000000000000000000000000000000000000000000167B49DB9A3D4730000000000000000000000000000000000000000000000000000000062851D91C485DDDA42F51DACD58609DE0D9844FD74175C19166FA11C88CA6BED3B48F7876838E0B1D9DA0FF851CA028276AFF78B97326D570472BD5F4BD0E8C7D33CFD67010381AB07FF830197AE85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014D300001D440021FC6401D1FCF800000000000000000000000000000000000000000000000000000000627BE53B17A3188C608378A45B32D706ADEAA367BD88E8689FE608817529943093BA102C277883E5F1B33C296CB882AED0B8BE84DE53B7BDF3567E30CBAB8874CB214927000382029007FF09844E6D7810830E3E959453BF833A5D6C4DDA888F69C22C88C9F356A416148801B3579539468E41009FBF10FC000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000DED7D569E0A9C346F0BDDE02AD332B4CC5FA3BE50000000000000000000000000000000000000000000000000000001BA95511620000000000000000000000000000000000000000000000000000001B85ECF66A000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000014DED7D569E0A9C346F0BDDE02AD332B4CC5FA3BE50000000000000000000000000000000000000000000000000000000000000000000000000000000000000014DED7D569E0A9C346F0BDDE02AD332B4CC5FA3BE50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C823E53FD263976E10935B91644D7B1FD5FB8C83F76F1E9C66B7069358F036E75E64023D5CE9EB8209B9CE19F419C5E604C3E23A2665C494C3ECB783FD73DDCE010382010A07FF82314585174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80D01FD32F00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE66AEB493FCDD17614EFDAF20DFA72D2DC81C0FEB59F811161D1B4029EED5E3E1023238552486BE38B9B11078648695751E2A68AF16C5642A299FCE5725BA44B165B00038202E907FF82BFFD844E6D7810830FDFD594E195A15533C01C8CD6B28F09066842486F80F8F280CC064C8C00000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001C00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000000200000000000000000000000056FF75567E5CA1FD2EEBE5EC0CAA37EB24CDA4D60000000000000000000000006C98BC1A1BF5282692267B76F4D12D401B13D38000000000000000000000000000000000000000000000000000000000000000024554482D555344000000000000000000000000000000000000000000000000004554482D555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000033C0C898DE00000000000000000000000000000000000000000000000000000033C413CAAC7FC4DDCC4BB16C170579AC4BE1E1B39C8AC35734FD824846DEBDF30A79E1B593725B2B4CE76498F89E58247EE24F84F0988C4C8AB968E8280FACD65318DFFB31010382012907FF822EEE844E6D7810831E848094146C57ABB43A5B457CD8E109D35AC27057A672E28043C8D33B00000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000018D531680000000000000000000000000000000000001ED09BEAD87C0378D8E640000000000000000000000000000000000000000000000000000000000000000627BE59ECFDB112ABC32AE9D2D039392497F2ABF161082175E00C0859C75EA616E7FEF90533DE3A3AC66D23773F85EE20E6F66397CD7A4C8D3080F419C106286197FD015010382016707FF08844E6D7810830FA4C5941B02DA8CB0D097EB8D57A175B88C7D8B479975068018CBAFE50000000000000000000000000000000000000000000000000000000342770C0000000000000000000000000000000000000000000000000056384C7AE2ED1C8100000000000000000000000000000000000000000000000000000000000000A00000000000000000000000003B378222FA3E3DCE3B4BFE07794CEE6FCB724AA000000000000000000000000000000000000000000000000000000000627BEC010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB178EF09F9EDDDF8B21E667513C2CBFBC4104679DC803435752C9752A92C6BAEBB19AE091386A7526C4F36A21A89778A6C10AF0F9889D45AF3AC2DC6003F6E7DF200038202EA07FF822B84850BA43B740C830FB0D994BA1BFD85432905FF4A2E7F516B56B7485DBDC5F680E0E90ACF000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006FD9D63FA34644454808E188956191AB016F1806000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000164627DD56A0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010438ED17390000000000000000000000000000000000000000000000004563918244F40000000000000000000000000000000000000000000000000000000000029609F55600000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000BA1BFD85432905FF4A2E7F516B56B7485DBDC5F600000000000000000000000000000000000000000000000000000000627BE797000000000000000000000000000000000000000000000000000000000000000200000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB1000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AC2FBCDD3519E32CEC7C8CCECAEE37DE0D0674C8D20D90DD534CFCA8C7EC7396054627342893BF7859D53D6043F076B28AAC2989F068C437DCA9CB71A7CB1CC0010382116907FF8203A4844E6D7810834C896494737EAF14061FE68F04FF4CA8205ACF538555FCC880821CAB0B0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000D00000000000000000000000000000000000000000000000000000000000001A000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000006A000000000000000000000000000000000000000000000000000000000000007C000000000000000000000000000000000000000000000000000000000000008E00000000000000000000000000000000000000000000000000000000000000A000000000000000000000000000000000000000000000000000000000000000B200000000000000000000000000000000000000000000000000000000000000C400000000000000000000000000000000000000000000000000000000000000D600000000000000000000000000000000000000000000000000000000000000E800000000000000000000000000000000000000000000000000000000000000FA00000000000000000000000000000000000000000000000000000000000000EC300000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000014300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000A10000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000049C700000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFA00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ED900000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F0800000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000802900000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000473E00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF900000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800A00000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004DF500000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF800000000000000000000000000000000000000000000000000000000000000A0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006AE96028B605D14353A83160AEFF948A772370A0C90370B53F18B9E2964C64CA30BC0C1C23079D0A1BB9021CB19DE0B1775FA801EAF613DF28A8FF0A902700D400038201E907FF821E9D847DB138B1832DC6C094569A11E9C23F6716073AEAE549EC69DE6356F9B380627DD56A0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013188000000002D8EE769CD34280000080000023962CA04F7D8C83D7051F6C05C7A94917B53D7B32DC76F90396000BA6A1F7E55D4DAB5356C4EEA6FD576543210FFEEDDCCBBAA923077665544334D5518597E175348849CAAEF35E3235913EBB49DDE4A0F0228E05A91F33815ECBF8973090F4A531B5CE4464490F0844D3039BA4467D1B96F82D4C9F11DD6E1E09A8B5C59D732B295D177361C63931EF48485BDDAB9002892E6EDD8D69900E175D414BFFE3C3FCB63E9A5FB6B7389F542D0FEAAA4D956891EA7E321B21E8D8489C338715FA5C16DF39E3DB72A82067A8EF94DC80239B54A66D75787643005668DBE4B934595F73DB543C76F90396000BA6A1F7E55D4DAB5356C4EEA6FD576543210FFEEDDCCBBAA987C776655443322BE76F4FB7B548264DA2F063F248521950705611DABB1000000000000000000000000000000472C57223A7151BAB7C80F5DD165D231B36F3A31F84F81F953674CBE063071CE005980DD2FF69BCE2432D679CEB191510CB34604AB7EE48017FA079A422868B0010381A707FF4C844E6D7810830943C694FF970A61A04B1CA14834A43F5DE4533EBDDB5CC880095EA7B3000000000000000000000000DCA5B16A96F984FFB2A3022CFF339EB0491261010000000000000000000000000000000000000000000000000000000BA43B740013C386C058DE7F8B0F01495534621322AFDD481ECCB530444D0E6EB1CF73298F12684FB222783C9C59AF532718A075583FDC1A76EA7C255D64A066F3CBC78944010381AB07FF830197AF85174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014C200001D1A0021FA0C01D1F1B800000000000000000000000000000000000000000000000000000000627BE542FB3192E75D82A4CAF0800B473194D9094B08411125F7EC4BEB8C3564B519CBF47365BFD026E60BFE24BCF5F192245F5610551BF3A303AD48DD572923C6623C4F00038202E707FF58846208D61483114F03946FCE1A7C3347E78D22C278EB3A5C72EC8FCEA294801E9A2E920000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046C0FE865545353311D61E247201A1DE3CA0E62E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FD6F388945D27E6B2FAA9CFA03D5ABAF3EC8C111000000000000000000000000FD6F388945D27E6B2FAA9CFA03D5ABAF3EC8C111000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034ED1AA80000000000000000000000000000000000000000000000000000000034ED1AA80000000000000000000000000000000000000000000000000586B1D2DCC85AD9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000627BE56300000000000000000000000000000000000000000000000000000180B3F770580067616E64616C6674686562726F776E67786D786E69001155908858929D000000000000000000000000000000000000000000000000000000000000000001E00000000000000000000000000000000000000000000000000000000000000041D5DB3E235506BC8FAD9B7FE5FC9D370A6F9E9B4DAE22BF6BF74C99843307A57B3DC0196718966459AEAAA0C3D994942A931B52FA18B6E8FCEE80C239A266D3E71B000000000000000000000000000000000000000000000000000000000000008BA9EC06484DF94734F59CE2D9F6B9201E318D7D89235DFED1F6CE2014ABA0D7448853BB342C5D495EE74AFF456BDC33C7A9E467605CB31DCEE495CFB9E4817A010381CA07FF82553885174876E800831583449487A4088BD721F83B6C2E5102E2FA47022CB1C83180D38AB51900000000000000000000000005FF25C26352CE316C183FA226ED4DE4B07E9E6F0000000000000000000000000000000000000000000000000000000000000035000000000000000000000000D4266F8F82F7405429EE18559E548979D49160F34DB0F0F05E78FD1FD6A1BDA037BB5954CC1C7BB4A085E8DE790D1173367D7FFD624F867CBC17496226576E743F6C502313A3D3D559F62EC60169C0E14EAA24D7010382010A07FF82314685174876E800832DC6C09469844CB44932B489F07D0F6FC42294D357A7B74E80742E9E0F000000000000000000000000FF970A61A04B1CA14834A43F5DE4533EBDDB5CC800000000000000000000000082AF49447D8A07E3BD95BD0D56F35241523FBAB100000000000000000000000000000000000000000000000000000000000001F400000000000000000000000000000000000000000000000053444835EC58000000000000000000000000000000000000000000000000000000000000627BE6724D713F8FF19966A49A5C13596E09BCDE2AEC5502956241835BFC4E294E6130117587AC8959DFE895B602417B93994A34E537666C11095F03DFE63F82604A2117010381AB07FF830197B085174876E800831E8480941A0AD27350CCCD6F7F168E052100B4960EFDB7748017835D1C00000000000000000000000000000000000014D200001D2D0021FD9001D303D200000000000000000000000000000000000000000000000000000000627BE545E4418C941F77FF7D80CFEDB3B1189B5F9FCFD578CA3581764704B6E0A805749F635B4CDCA426230BDB5B821BBD4C98F17486DF65472CC530617FCE6B0633D6EA01, lengths=[0, 1038, 0, 139, 0, 140, 0, 363, 0, 1038, 0, 111, 0, 234, 0, 397, 0, 1038, 0, 270, 0, 526, 0, 234, 0, 2157, 0, 104, 127, 0, 1038, 0, 331, 0, 269, 0, 270, 0, 174, 0, 204, 0, 270, 0, 236, 0, 174, 0, 174, 0, 269, 0, 270, 0, 170, 0, 174, 0, 110, 0, 102, 0, 589, 0, 1038, 0, 1038, 0, 174, 0, 174, 0, 269, 0, 236, 0, 301, 0, 174, 0, 340, 0, 2170, 0, 174, 0, 1038, 0, 174, 0, 653, 0, 174, 0, 105, 0, 491, 0, 301, 0, 397, 0, 340, 0, 493, 0, 589, 0, 1038, 0, 1038, 0, 170, 0, 848, 0, 204, 0, 429, 0, 140, 0, 174, 0, 1038, 0, 556, 0, 109, 0, 170, 0, 174, 0, 1038, 0, 172, 0, 269, 0, 683, 0, 139, 0, 1038, 0, 683, 0, 685, 0, 236, 0, 236, 0, 170, 0, 1038, 0, 2733, 0, 170, 170, 270, 0, 588, 0, 1038, 0, 1038, 0, 491, 0, 236, 0, 1038, 0, 491, 0, 5133, 0, 493, 0, 683, 0, 1038, 0, 110, 0, 174, 0, 270, 0, 172, 0, 170, 0, 173, 0, 493, 0, 1038, 0, 270, 0, 829, 0, 171, 0, 172, 0, 589, 0, 127, 0, 2735, 0, 301, 0, 1038, 0, 204, 0, 170, 0, 109, 0, 301, 0, 170, 0, 683, 0, 1038, 0, 3147, 0, 107, 427, 1038, 170, 0, 1038, 0, 749, 0, 1038, 0, 654, 0, 270, 0, 1038, 0, 1132, 0, 203, 0, 748, 0, 365, 0, 170, 0, 269, 0, 139, 236, 0, 174, 0, 301, 0, 269, 0, 140, 0, 750, 0, 1499, 0, 397, 0, 337, 0, 337, 0, 109, 0, 174, 0, 107, 0, 107, 0, 301, 0, 174, 0, 660, 0, 270, 0, 749, 0, 301, 0, 363, 0, 750, 0, 4461, 0, 493, 0, 170, 0, 174, 0, 747, 0, 205, 0, 270, 0, 174, 0], sectionsMetadata=[164, 14755908, 1652286576, 456129, 0, 162, 14755912, 1652286713, 456129, 0], afterAcc=264373FAD115E6461FEAA72C59343D8FC8E6970D92D330276052FADD8ADD09C4, gasRefunder=0x284c1875694058b213866F5F2aD015b5a4B9438b )
GasRefunder.onGasSpent( refundee=0xa4b10ac61E79Ea1e150DF70B8dda53391928fD14, gasUsed=260235, calldataSize=102116 ) => ( success=True )
- ETH 0.18202944434666328
Arbitrum: Sequencer.CALL( )
- ETH 0.18202944434666328
addSequencerL2BatchFromOriginWithGasRefunder[SequencerInbox (ln:160)]
gasleft[SequencerInbox (ln:169)]
addSequencerL2BatchImpl[SequencerInbox (ln:175)]
calcL2Batch[SequencerInbox (ln:260)]
includeDelayedMessages[SequencerInbox (ln:280)]
messageCount[SequencerInbox (ln:343)]
inboxAccs[SequencerInbox (ln:344)]
push[SequencerInbox (ln:297)]
SequencerBatchDeliveredFromOrigin[SequencerInbox (ln:181)]
onGasSpent[SequencerInbox (ln:189)]
gasleft[SequencerInbox (ln:189)]
File 1 of 3: TransparentUpgradeableProxy
File 2 of 3: GasRefunder
File 3 of 3: SequencerInbox
// 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 3: 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 3: 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á <[email protected]> * * @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); }