Transaction Hash:
Block:
17071690 at Apr-18-2023 06:06:11 AM +UTC
Transaction Fee:
0.071844990235266429 ETH
$146.19
Gas Used:
1,843,011 Gas / 38.982399039 Gwei
Emitted Events:
| 239 |
TransparentUpgradeableProxy.0x5e3c1311ea442664e8b1611bfabef659120ea7a0a2cfc0667700bebc69cbffe1( 0x5e3c1311ea442664e8b1611bfabef659120ea7a0a2cfc0667700bebc69cbffe1, 0x00000000000000000000000000000000000000000000000000000000000bdf82, 0x7f5895460e0c35cc1fbe40a2a470e048a4065701ddc6a00cad9ab505ecb47c0f, 0000000000000000000000001c479675ad559dc151f6ec7ed3fbf8cee79582b6, 000000000000000000000000000000000000000000000000000000000000000d, 000000000000000000000000c1b634853cb333d3ad8663715b08f41a3aec47cc, 179639e209aadc114c04ef6e29bc32f64818a29f8026f7abf57365ff9d193a17, 000000000000000000000000000000000000000000000000000000090ebe1fc2, 00000000000000000000000000000000000000000000000000000000643e3353 )
|
| 240 |
TransparentUpgradeableProxy.0xff64905f73a67fb594e0f940a8075a860db489ad991e032f48c81123eb52d60b( 0xff64905f73a67fb594e0f940a8075a860db489ad991e032f48c81123eb52d60b, 0x00000000000000000000000000000000000000000000000000000000000bdf82, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000094, 00000000000000000000000000000000000000000000000000000000643e3353, c1b634853cb333d3ad8663715b08f41a3aec47cc10002eb1091beb75e03fc91b, 9386eae4db77695704c77ba6bb6ca2f604d39ab1000000000000000000000000, 00000000000000000000000000000000000261cb000000000000000000000000, 000000000000000000000000000000090ebe1fc2000000000000000000000000 )
|
| 241 |
TransparentUpgradeableProxy.0x7394f4a19a13c7b92b5bb71033245305946ef78452f7b4986ac1390b5df4ebd7( 0x7394f4a19a13c7b92b5bb71033245305946ef78452f7b4986ac1390b5df4ebd7, 0x00000000000000000000000000000000000000000000000000000000000261cb, 0x2aa8835ef48c556c36927bcc8d939d83fc7eea5925e59854958599a7f7cabf15, 0xf885fb6cf06d01b1fd8234578d7e34a11a0c874f7dacf51a99195a50d74ad80f, 15a7c645e1a315e5f3b71e1f0f66c45ac33e0a9b48d6fa64bf790437e73fb36d, 00000000000000000000000000000000000000000000000000000000000bdf62, 00000000000000000000000000000000000000000000000000000000643ce1d3, 00000000000000000000000000000000000000000000000000000000643e4163, 00000000000000000000000000000000000000000000000000000000010467ca, 0000000000000000000000000000000000000000000000000000000001047e56, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 242 |
GasRefunder.RefundedGasCosts( refundee=[Sender] 0xc1b634853cb333d3ad8663715b08f41a3aec47cc, contractAddress=[Receiver] TransparentUpgradeableProxy, success=True, gas=1879343, gasPrice=38982399039, amountPaid=71861141692223342 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x8315177a...4DBd7ed3a | (Arbitrum: Bridge) | ||||
|
0xA8C62111...c42632f64
Miner
| (Fee Recipient: 0xA8C...f64) | 59.667076825523211807 Eth | 59.667224915845270998 Eth | 0.000148090322059191 | |
| 0xC1b63485...A3Aec47cc | (Arbitrum: Batch Submitter) |
5.001764291654351334 Eth
Nonce: 104838
|
5.001780443111308247 Eth
Nonce: 104839
| 0.000016151456956913 | |
| 0xe64a54E2...80E2E4eb5 | 687.829922997148513713 Eth | 687.758061855456290371 Eth | 0.071861141692223342 |
Execution Trace
TransparentUpgradeableProxy.8f111f3c( )
SequencerInbox.addSequencerL2BatchFromOrigin( sequenceNumber=156107, data=0x005B36D05444B2DEFCC317401455B51F362345AB8780AA4542E605AB3F7EFDF9E7BF7F068EEBB1CE7B80AEF9CA580097B5202C2DF2A31616D7A5052D686151ABA555CB5C5E0DE0DCB673389D7242242544A43D29F47F4A38C87E3891126DFCA7EA0704EDD1290822562091062516184895FCFF6CEA434354A062CCCC09B1B365F26E1B5A4FFA49268AA6137BB49D987D37EBDFD3A6F1A919E4B2A484C8828726B04048C5A8F967BB61DBD9CA7F918AE82A70FE97D89D574C4E5D06689D1F222B5E548CA3A72763A2A68799898D4D6E7222FFFEDF54FDC5425C082B7577BAD2ADD0A5FEEE52B8585383255C56E160444A4317BA2D201750837D6FF7AD1A680B1435198A2E2CE98CC72640573AF376DF3BF7822216204D82D2188BD5C80055093762298F038672EB24D558D30AF9EE6A42EE2E523A4B4AD312EF61D5E0CE8C480F54E8D61E40666609A480E24F49B37BD229A6D1907F93FE95CF2FD993F92791BF7CE6CBA5FEE5B37EFC65FE6B6A5E35B246602CD094AF04878B94788C7281D04981AC3FD2289164A991A2F58B63E74576B26497642F39F04633FA23B0B591CCB5652F380E1028F8BCE5B08B24B97DAF76F65A246FA4B844D7E5C365965DC4535F4FC87EBD9C7A3CD1E1B2F1B187D3C2ED5AF8AFB1FEEDDC66B6852433964F1111105ABFC950FB6F06767FBBC6B5BCAC836D6C9A90645FC6F6FF67F82B7C21120326750D14FEFFC72AB0FB30DB6292194FB7A5B82102C2A74E543434D2469C97261A16098685C877684B82A0A0DF1633AE610F171178ABFD91488C98A0085E7AE10C609277DD55F1DD6F4F1A2B7D7F96575ACC81E150787BA4FC838806889AC7B5CE8560299835EA3808D51E25D79185CEE24AEC7AA54F30F40BC07C2F231E6ABA0E24FC0089002B4503736B796FD16C58855C314D52A9B805F0764901B1223D468B7006466CA47F8A3F003ABEEED4381F0518A97C5691EFCE8F81DDACC0AA46DDB890DC0914D2A6C22E820FAC3D403B619047686B786903041E89F4B3141EC1412794C1FCF1A0B3A04A1FA78697AD3E46F977C8639E20550CB2F8C143A75B4E0754F67CA37C6A3F0A01A65AA6305050E40E860AC6751D96471064FC1E750ABA3D088E87609288576140D0600268D32DB05010512C50901206F8064147EC9EB91714BD682AF011057C79D881554C198B522ED617530B8C8D382F06F4C88A571C91C88F6A127E509808EB3583FECBA097902F3EC9A54AE192753048C9880F222A9882A2170EB86FC9E57F8892DE7B132B900E15C096B64315CC921ED9C0AC3552F0E61B9727036C9BA5C6523B9309CDF15BF7B624147F9B0B101A0C13196F38A76B4ACABCB6F47DCE77B417ECC13D02995C3A1267AB041411A723992187BDFEF7137C6F4D94E81E958EA27F7BCE4E3631061A69A7A7BD09821721D2E30D09AF06C2EB6EC80B3FD1313BD7A5F4D36C29DCC469C65FB1859CF53EED77019CA8598F81FCBB36D91678CF722A5996EFF05D35F90E392D8F624AFBFEACDA88130F6A7CB57AA80B2F6D60834722A35DF44660CA1566047160F973943597AE2E3D8566E4DFE49AA01545C1DB657B3FC463A78CB26448BDCCEF0956A8E1B20CBFEDF47A114DEC918FBD85A0E88503763FAAD19C36F7DBDFF127CDE9A9884A8C638EBF95F6F1B7E820BD131C17CDD2066C0B3D55790F2D5E9E7FDF0BB7F2816F9787FBE5ABBE37C227428FA6B255AFAD36E175EA06D8435D38456724DA493F2882E4EF5C865E48AFEA8CF37964F6D5AB037A952CB8FF9C5013DE2E6BB03B67B261A59F573E841FF09099F8391401568A02F8952CB96B7DF45B505CEFA92CCF666C1DC73A72D3D370387B35DF817D7F6BAE01A8DA2EAC865E6177CE95492A643F4EC29BB9B1F083642CDFCFD6A1957BCE3D9C36FF952A83411E8AC24B1B222032870891BE7C19A008067A202365D919DE276DFACA48F9C4A5AAC99CF3828AC2026F516F7B3403A316A042C0134121DFB202C63A5920EE6D8E64A1A64E9F135840A0D1EDA04A4ABAA5657C44ADBE324B023167B4CA69A25E38E0B4B18C7623FB4DC3F05A5918A5F0B7D42DB78279AD32BCC1D5A453EC4107731CF0AFF8A5D3B5803F3BA156AD112E39D5F6BAD9B0631EB0CD20475DD83BF689B5120402814079248E68525D8B33FEB626E3DDD11160624DE5FD9B84E69459A3ABDE90A298ADD9F6F828404A7E12A07850D43B718D0731D0940E48D41D14ED0D36E9D742C5B99F7421B70A657A25FCE02FDA54FCF2B5D2FFD85825EC0807A1053AB6008581F84EF0E1B9E92B51FFE7A1E65117C4FC72DC4C07F4454E36B71D1DEC844E9E9B322D0CF2A84C115EDA80BCF9FD3B853E66FCFF9A055C2B9DAC845827B3FC18C58EB118531F8632710007757CA889A12295DA4C48E1EF86C8228501895C1C749292AF940642684169E567605A90C73DC811A46A51F1FB80DC302F0C468F058ADC410D90654C004BBA83984626A0C35170DD21DE061472145A146613387ADD7A7FF176070846049B8240E59C064A14FFB1354552C934E1FD08282C4F87E6A055CC791B2101547971076280A8D436E2BC081A2D1BDB5E84F5EC2A3FBA4BCF043915F29EB513A4EC720EA24041C7D8002258DA02548830F440348F016BFFEA8CCA11736C2869B3E213849651591E27A6AE69A7E91117BB39B3D809D477B901E202098118F141A0A7F277A0E8493759BC87872D65106D64BAB90156A53797BCEA26B2B9A96B9A952B417A0B40499CE8A93D343BA179A97687F995A250FB26BFB236AFF475F718D620E2B376ABCFE3F74BAAD11CCAF9BF328E9F44B7000E1C79F8321FEF64C7092D693694C68C0844FD5146B708C3ECCB90D0CFDBDB4DD2769872478ED5D8F8669E89093CC7C9F2F3B8191E40638E2E6A1778C4EA09972BE31C3689E2AEFBA8A92C8F1353D77475E87D61AA37C293EEEF7CD88386B0EB336E78C468988AA0975F5C49856DFDD5AC9F4F3F90B9C2E7C14B5F28691EAD21C36454FCE08DB427E5F1E1A754A9824A3E66BF2CC5F22D27A3D02743F5762697935B3C5A74E561B85765D8F09496567CE12174F7AB9BEA72A2C47C3171B98E623321D70CFF5E44E6C10231EF623505D98D279D8BC30F426CA92C8F1353D774AFFF9D3D5B6F8427DD8E79253720ECFAB4E38EEBE98DC3DAD93F4744CB115C09E866757577FF74DC5B8E98D550A47C92AF2DAAE68A6064179D5FED3E9F5A5DD64596D3B78A0E3AEFEFEC637DA459BDF2CF5BC0C5BD951661D8BF3C6E292A2AF751BFACD747CF7EFE30E4C37C2613589E92A5EDA919FEC95F156DF6523A9BD5464C3C5496C7576CE87BBFE4FDE17D387C9E478038CAB5596FC0778FD1453341E006E743F9926FAE10810BC5F44CC2B27E192C4207EB0C5FDF2E70BA907DC05107738C3B383669D61AC891E13F4904CFCE655BA17F4A4FA798BE3BD74AE0CC4EFCAE39EC634C1741DDCB645D57EAF58AB6783F198AED5F75E9D510BB0E4D971A3628585953895E586AD5B3705E2C452F7D8C0DFB1219F6DFDBDE5551FF1CDCBAF2A1D2123F921EEBA93D59212C78E01F08040281E2FAA30EDF22AC432E2756A853FFBE8BAC14978FF89DEEC9CA18222608A626CB506A33FC6363A0EEB8539325AB8DF8B6A82CACE0D0A71DA7BC997D0F97849E7CD9CA49F919996157A4E0A23F6837BE4202A516BB50FBBDE8B2B9A053FDA9D791C674BF5873F5CAD55EE6E4C29481DF8160C35E4939098A8D8B32BA45D808CB854CBBEA57F55025AEC78F63D251175DF4379820C4922CC32CCD700B5A90C5D9243388D546C27554662B38F419373001DFCA6B03B7ECCF4769B8303D38D65C9600523BD91DF7DCCCFE925E8DF424FEC39C2079AE53EE13E2EFAEC91274D21864044C0A32D0C4A57F9E9AE4E3CA23B408CBF941A3EADD5B2D84B178B683576D9F8C70779E8309ECA2C9F243B4195E69F78EE83E268B9ED5C677E2A84C2B38F41937D8D6C78A2B86A24479BB3B2F6AB28DDC707FD64D722EC740411F673D0F71FF22468DC1BA64BD1C647E18B4448C8AE2877B07115D7ADD0F0365421A3B2112FF0A6811B6DCFA0FC06A79140CB59FB7AEAE3A7C93C441DFC404A1E064190E6E960BB5253105089B28D3689443655AC1A1CFB8413233A43C48B4B6181059DA6B254054C1784F538B457AD0B453FF29D7CAF4CB2C1929DF53678CF0E9CFCB3AFF22617BA13DE88FCF9347746F2C9ADB27EEB0F3615A8435382EE64791F5220E81EFBE7D5F677DA02570EE25C9ACEDBB8B2D8B7F7B33DC0199A1C475EF872AAB8D640DA84C2B38F459CFD157B8E3210C90F030F9E6F0C9690C7EE57934FC8598D10A29F099DD2B1AFC1AC86617352C9401D35B757AAE9FC8EDFB354F0F2F9FDAA6D0FD37CC5608A3E2CB07E5C82847CDF2CD9F3D0DA27162DFF8753D8D7CF27199CCA4050976D7FDB2EE02110D461E9015D9C2FE93CCE123953AFAA82288905EF3C2A00F86FC41FA31D45E27B0EDAB161B4EEE6C4D4070522A29595E676A172F28223987D40430E0066491428120652C248F839C3F9800859B00DD74079606050ABB06120D44CB405084AF8CC72D5597D1A0CF886618D18C40342312CD48443332C644414003D5114D00F7BA035B07E810B88524777A8540551864B8DCD91482E44A8D52861624AA45337899688618D13292681948B48C235A86112DA388964120239A4789E6A168862C033263428C093126C4981063428C09216ABFAAA30E1ACD106075CCBE56B647B4FD743FFE7AC180D551DDDF0FCF5FA9A984836028337E96E4A5E3FD5EFF03C54EE28567C45078F581807DEF9D2A5304E9943643BAEA8A88B0ADC05D4C7626BD441C441E5305445FFC766F10ECC13D02995C261267AB041411A7239971E464E621B7F31379DBE604511BE663AB0AA2798C8146DAE9F99FAB140676371C2211F56202D143049F64B170B6B74A11C97E7BCC389C5A61E4302007001A2C7A5FE45C02850AAE5FC45028A9641A6DFD1CEA561B503B07510E3BABDDB13B90B4CF85B7D77C6090078FF0D286B0C648437B4E50A4ADF6152802A9173B23293AE51FD384A80D813DC373B0D44053C31F663578E47D436C592F1CA0AC1C45E8B513FEA2B480F1D17D20131E9352CDDA765D36B48CD826880D83C900FAEA6356EB83F7D1B52A710C2132347F27707BC6C9353F0A2678055D2AB261366C4126B39FB06F0BD43CEF8C9F349757915D13C70C493731A585FF6893E6C425A30E7F97618322CF72B491443F8494A513F9F85FF4AE8F6CFB9B8B509499A1AFD1CEAD49CA510847A4530B613FC06B6C9C487DE2A7BF9C50C416762BD16F43E12ABC98B38AD67DCAFC4119C4110DE7604D8B39C9B89BE419285B51A987F74ECEB7EE4D53DEAF242405AC6CACA4A844C8EF94255D993E56EF2C127265837DF807BE00C5A238330DFA126377B99955D25B1527A5A153C6F10B8FF92AD446477A91F2360CAC2EB5D778BE63F1742FCDA80324314CBFF37A27FD8DC44BDE64F717F2969D96ACF094FFB7E58703D10F2A0D7AE55B132A087B84BE874722FCDB02457052AC65AC67805374F66C575FD20B83648B5C0825AA9AB86368A3AF5DFB341E3A2083570172F2A008D2B610D1F6A918C4A2BDD2D6101F1F903DED88AAA0945AB3F8051441279733CD88522D4B7789ACFBA71982D980FE459D99009184953DC6A1B227A59330EFC31A0C828322E7345084316F9ABF555BF32B2A836993EA619B4D12BC45C2B48778A928E9A10D8BEE197D42863757F854B4F728866F062236B0221802052182BFA7013F2130C59B5E673AEC5D77FFC346C050C4E37F3BB35FEFF1D568EB36BC5E4936381E69A73BB31B43EF464B4A4BE24743608B3FE9FD5389A16669D142A7F22AABC5C71DCFACF4AC7D0FE75C8669EF64946E92185001721843B3AB98ABFFA0F3ED66C02D354702F7B2459D9AC78EE85A239B6AA20CAB9E1B3803067904A7849736989FFE675B14B57D19A39EAF13F33AFFCA5C4007D81D98B754E48DB249F00E305D8D60FA8F2D2B3F30FDA08A0C1728EA16427A7EE9BCF4FDB420E7332CB2EAF89E8E73EC1094F7CB295FEADEB05D6B12BFC101A462D9880BCC2C37800816834E7AE7451ADB5E9AEC3B325CD8BE9CE16BB836B0FBD556B1170E98BBAF07DD2725F768973632853D8A36CE9FB69860DCFE62C1C14E9A77A52BF50008B52ABC4F09FEA544A97B75C7A128BA6F05ECF52CBE38A3E3ED17791BCE6CBD8140201008046A83411E9AC24B1BB423C9A76C4151C8FE3FECD42250378832508AE7142866E54D82E521CC376AE88081BC0FAE527FE763907C2D79313DD1BBF0E1D8F4B5A5897C8D9E5837C1417C53CA00C356D806C83D3DF13AAE9C84AE46D91DBD9790ED8C94C3D8E09DC90C80DCBC180E0577A0365C5CE3A13DD91FA11DE1A50D144535FB9DC5A408D6E88A0C5CEEBFADFFBCBEDE4D3BC8147B17CD1F28BAAAD54563E04254BFFDE880CA8A800EAB4908928B011050B225ADFF3DF619305F1E6EB3A76D1B7077EA065CA80AFF1920D3BF1A08C1FB0FEC3601BEE22C2C6F5F502D0165B222C5F7A512A6BBDAE2DDAB26A3C8322FA6D735BD313EE3194EFABA4F93D8FCF97BCF37317E7A21116C9A3E494D18C89E5E961E1F2DBD6C57F54B2D96A3F727375B0F0E5B3F6B7B4B978F88BFDC1D5638A3B066882D2B3A09EB3122ED9F3BBFF13FD7390A8A5E30C05525AFFD36D8F17A14EC1A13A8A5E5792486F761F66D3F5F597E8DF577AA6B0C8018D1381D32111B32255B6729F5A69363F14625ACAB0E3B3C65FCB9FC35156FD5ECFEA1F564C3D2BA6AD85AF1F969D93D270AD53D28C32F333B45864088026284257A98D4AD895D4B4D5DD091AAD66CED63F9DB3496799BBBFBB8B837139000374C9003DF9F797602417A1DB0EEB7A2700C4D8A258137B54FED206972C88F4CE2C144833E8271C34B1B642E549EE067BB3A00EEA2A23D49FD6F58745B9F69408A9EC87E455110EE0F2D384AB7788728420ABE5FDF07EC191422744BC489AF3C5FF6877EBE045384A5614503DB720A043890213AC7A3F17B5820B109657D9C1FC25D12CF33E44088C14BFEBB07DE45F6D50670A6D58FD55D92D17F1896B5ECF83964BEB703C02ED18F7769FC787B8FA4A4CDF51CA0BF618FD0D9087CD9B4070FD454E5529F328882F957B7194954575996B954C3AD923BA89752E11D501B7ACEC03AA281ABACF3B1877B57ED6CF64BAA16DADF4D6F46B6F434AD6B7108DA41354278D5CE0E970DDB5C708DCA8F992493851454E1B4F75D19FC792F2DBA7819B30CC4107ADB83789D2055CFDA36D68175FE38BBB3D9CB46FC487091DF36AFC8223FC241AE6E24996E0190D49A84D426F7AFC97B8DD8FCC8112097FD06D6BB0B122310892A2E81261C543D73B8F5CB2CABB494F765743B63BD9926ABE91507D218A28EE2A27DAB3BFA4269FBF69CFEBFAA81EE47C1BAD3221AFC60069E04FE17C33BD2CBFD6F08E7F655B9095D73E4D8E28FFEC88314D95AD32DCA9779F6F57F3F85ABDA7DA2660954A0D3F315DEB1C608995B00FB83A79280A83737C33779072EADBD7B129038BD675B5B39FA40E85FE3AA2E53B33998376EFB2ED8454EBF74A8CFF092FF616513772171864DD47E31ED8AA26ACD98BD2860906C0B3E75877CB7E212D407180B10907DFA1122F7A3CB13C6F6D53C89E7A20425DB0505CD74D882AD85203F78E38DDBD6E99B26C561974EE519A9149A2326FFC97E1EF1E9233D96A73AD745175FF7C319225BF437EFD24AF294C26E8000A36EB934EFC9AFF621DFFDD7F8996DD052C5B373B309E831878DBAFD4429C33AA0E61D428335C21EEA2320CA8B15D61255942533EAFB425D22B2B2172A5CF56F193A2EC083679811C5CFB253FF70CA60D019C512E3690178A34E7A6C64027F09FCEDADE7850A77941A46E37AD488CF84144FCA7FF4B37FFCC827BD02082385FD20E95340D24FF024A4A6A4FD7DEB37E26F5FF9D69B609C794F6E5A3EE820793A4856CFB0D90BE6E2C9BB2D5086F6CF08615367D53FB1290EFD6CB163377AA584F8D1D2BF7F32080E7640E80A7F625FF74C017DC277C74456FF8160B95F0E25A7A83E2A0D3EEF57BE66714920526AF07B83C10C5C0630CF34819B40D52DB2A508D1C81D8BB053F8D8EE42E4277EBABB0E95A5170CA0508E54DD7C170371791295D1D297EEB27FF9A11B73EF8AFD3929C0D43686890CC04C5F9BE96CC562743E4AF64AAA8E470CB77E97F43F6C74FABF067F980ED9C78D0E48FD5966AF53EAC985057A358C7947AE173A83FF08FD7241F8D9043A6C43304403131EB7F4F7FCE62543F7E39D037445965AB12AEFDBC0EEBEF043626FB7ADBE5D00538AEF14A09E91EF53F06BFFFC7FE10E3D2F2DAA0DC9A8E30AF7EF1982B8B348D8EB4E833C5C87973640CF92330A4F75280304320350077D1BA0E80751884A2E89ECDBCAFFE0EDB18424FD94B6487C9B6D3B2BFBF42D4DE8240FB402A6BC082068E5475D830133215546FA37A53CF20448C233B352BF705B970ED6DE99311953FDAD124CCCF131BBEE9C200190D64961B8F3E49F9298DB67AC9DCABCEB1497D146E6EBB75BCD839A2342E31535C01DF6E002AE2ECE2C923F65C64F5DC5604DAAE9D5D7F15EDBCCA7D27B2DFA9EB718703096158E7DD2D30F21595009DEB7B7B64FCBB671D50EF3E7E8FE2F4152EA56CCD41952EACCE5C006D89C7CEFB24B3F6377EFC925F126912D96C125203914EB5B01A44297A0ADE40ED80BD6445E92033F46BAC3C029234A45CFD0BB99E307EF6A034F1E07D9CF689BA31BCBF64A1C1248CE610B6386E709E226B5CBCAF0EFFE86E5E11A897C4BCFB1EBA7F417EFA80F002BC7291CC11AFB7A86ED89F322AA2AB12EBFB2DF393F5AA32736D2CBA78BA7EE3AB08573EDC088FE30C823A257E9AA8DEF4DC71A5A7B52A8FE5F72C55A4ECB23840C22AF3D241EF00E44641EC1BC078D107DCA06D1DE5E030B2592603BE80EEE318CFC854A2D71C8F430CAE7F4328B8DE85D7E92A3A89333078FE436ACC21573ACC29EE4ACC25A13ACC2AA79ACC234BBACC2A88AACC2384CACC212619884D869BF784BBF8E840A93E29593446D6340C40809B926482E36D1C7232F50B0189A519110FB05A8FCB827BC433B9A567D2D95BA63DF97288AF67F7B1E9E61EDEE4944C8B079E8200B4CDA15A621DC8FA3339D6D5E79057FCFB83B2C2CEFA90BD92F67A413883C480CFC74447FABD6CCEDA1089D5D0EB2B001286495683253B0F9608D59D66A86A6607785F44DF137D81414539FAC62AAE8796741C8812033A349882FFA14D988554669F40560178D59ECEC25F11A93F73C413F44E7D7BECDC9B2EC56C098D25BF8DCFF71349E7848F63C8764F04422791A4A46D00866B57D360231488E68FD29F2BE3FE31B2A24EB4E1BF6191537FF9DD463171D9E6FF13DA51BEB4C315F4559729DA47C94AD3D3073311DC91D1BDE74732592EBB05526A537150F8F8B6F402D381D638786D012934B67ED7D341450CDC824F61BD247A10A06380D3396EDC2FB9868A97DE7FDC46F2A230408A65927DAA0B4DDC8855A62748D21275803F6085661AC044FB4CCFDCF0C39EA34078FF24FC64FB6CFDAF9F740BF2195460D65D88D58F23BD9B2BC1F3FA2624C8B05EACDDEA292CF96FB87B54040DE9E1EF8DCF6CE71329540223B048E6D5ED04FEA60C1894E3FF977A6BABFF8B42A86FECE399BEB480A56144522824456C2E70CA8597EEA647A9F30516CA8791E3D3E1FD07F423830CCF7D10CCB3F227CEED644919F683B0CF2D01C5EDA100E26BFD1E81136665433C3E5FD52D67E91D1FCF68462E17CFA7B74D72C3C92708B2D207AE180ECE7314C954AF7CC0FEACAE6CE942BD4D1CAB239A1ADEEA20108E76C66E4C13280C9D4505394ECBD4685D61DCD774E6A1127FEC09CB18EA510B71B14662FB57F008E6EFC06E033351696C08687F294930205C2A6741072E8A0701AF2BFCB63A4D859977E94A335F9A865EA821A7D61A423525A92DF02AD3D68BD89B9535DD203A2DCC0247BDD8C24F219D2E73669B1F3914B642DA222F624B9211430CDC8EB5EC261450A7CC4DF1279604E8806CA03E46BD9A92D50E7F9260A1C11AD0ED80D78AA3D3747B03DC8BA0F3212CA628020411BD9969DA57FD00B9EA9607D9092DAB91C0939096134114C771FEDA5DC6D2CC4E34558ECF5D2930F4B8491441F0CC68314AB1B323FBA4042F079E06F24811005BCC07910A28B351B9B50919786BE36AAFCA1A7ECC0645EAC400A79400AD122A601E89FE99EEBC366851DD746E729CDA53C5B3422602629C8F761BEE8F2585F44E88907AF0EFA085E0C2F6DC0EEBE787521F67FCB20ADE9A7D2C6D596F11EFD0527639C8B70B3757E8B01DB6531F102DB1D601B9F4A945C0407319CED274FED4454981240DB172B32B1DC704F51DE517B28AA7E885A315A281A09EC19B7E1D9870F7C446909C1C379AC428945BA76395E0A49F5F716E69230945EB7ACF2967B8C9E6CC9A5027319A16EEF41FE8C002D607F60F850A43D9FFDFB614773F5A9E5B7A72A64142D2C9AC50E401A400BA9E2329A86FE5E164EFAD3C4896F36118F34A338D2412226E6C78A7DF66781B50FB3464D8B76764570C295114455F39F5E3E78B3831DBA3B380FBB4A8844DE82B7EFDE7189FF93AF88F4AE956F2B7D77DEB9EEA60887799AB9DDFA3DAEDB633364A2DB8A29A661A8B27A530848CA0225CB483EB9AE5DD179A0FDCBB1D5A721A00AD5AB8AF7A699F3EC93FA7AA421EAC38E1263C92FE701EB177E9B3D7B49EC6684CFDA9F3FAFCD6CA12AC41CAEC6932A147AC100503A1431D6E8A70057246DFFDA22F44763155537A7B0EB47B308625338CDC621A02D9A46E143F047055F154A3171A0A0CB1EBBA5C89BBEBFEBF324FA3BE458AC96F0B50530C843CEC392AF0CF382C1674A0C0594011505FDFFCC728B6617F1AAED2E88CC5DD64EAE0FAF0583F3D5D60225C3C122F3594FD8F8FFE8C904DE50FA0AD4C2A20FC86A83EF37BB10C57FD6DA9B2E778A6DA8D26572AFA67CF939235402904763154EF9920836BF9754A49961A113B28E3D385350C667DBBC4FF5C62E3AE197907AD8430D3C12437CC92F02757D7E9C98E070BFBC80A241C0AE7CE6DA2FB562E95534C6F5E2A3621D75B136ABABA305AD5FCF745DC2768BE9B3C6C2C14E1D82DF0069E2694724034F27E6A86F42C9C63E8D0321FF90AD61E9AF4585CEEA442E03D5BC38502B0CF2D0185EDAC012898C1D017CE70889407DBCACBBC90A0E0E0EAECE79A38E6F6B4ABBD90AF3BD70164238371C5B79C0C9FA7130245CE69248C8F17087F3299C598255E3D1022A3F69B07EE83916193D6896D51FE8032CE93524B56A7A77994BADAD0B716E82EDDF47DE5519B8FE3ACD783E0A579F60E8407A2CDC9F1B121F0CF288C4155EDAC07BF6C533F9D50C057F5C6E56DE8D75C5462DE8A1E494D8C0B80FF7E11D8843E6FABACCA0C8B9E12CCBFF919D46A64C14C927F3A34E76FD8A7A5B0B273AD6502CA86DEFF51654325673F0DD2C3D2C3D7D2DDDF4F8E46D6D65FD5D2C3F395883A2E110360DB40FA0A1712E05DAC7CE80AAEC7F86348B8747CAFF0C45396E465FB7EA68574DD2F986F253EE8FCB5B11E23B41AA93658295EAECDC9460CEDB59B7D2D16C1DE3B5D180DAF6BE0513C09BA091EC200F07442718810E14E83402CC7056321BF1181BD797477DCA5819FE58815D816F272C4FB473159CEB26A03C20CB17D722CA5B28A4DA54667C37F553F9EEE13FB9AC78A2201018F93E1BD6F530F92845703F34BC4EE5559787322C7FAFDC5F1567C0040DCB68B16BC9D58644AEE7FA44140B1D8C9916FA48DABE0CC2D5A1F12FB80F9AA055233A830E41B640C13320D51BED3331529CBA80E02EC7FEB899DDD21295CEFED61CA367E648523F42AE56D4EF5F4A7DFABD001B2A26393CCCD3B122D98AB661CB46DD83DF71EACB756C101EAB7083E8EF966BE3A61F69114A447D32C8C84B42D77FC10E5ED1BB1E4ADE945192BD60204AF690212586D7EA609C66B6892B9B4C0B04EBD70CA6D6413F98C28757258B00FC1B17B99258A7532ACC4CA6E5F83F5A0AEA9ED43228106392A3E104C3587F1E3A903E5B3CA82FEBA1BBF3691BECAB1D4472C7271A4B5A32A3AE78BE88A628FEFFDC9EA1640DB33AFDF330C49C2AAA0A1ABE872B05646ECB9F6428FDDBF545215C5B1472ACF09434375EC2A69C3492B2057147E221287AC1C046E6F0F4E8CBC0EFA38681DFE3181B76E1D17946915A84690BF97FE2C6859830005A3332AC3A5EB2237371F22F6BB46F951F3B3EECC4CBCB077F6967DDD2F80272C0DE42D55358243E47AC690ECB1B7D0C7997855FF155038714CBED2FD233D772D5F48C84477F0DCA2DFEEF3D7A19F6101A6A20D53DFA8AF0268A8A4D12011068A8912BF8920D84F8CEE12EE90C4AAC32CFD9843DD27E28E80090A6BC262ED1416F75D00BAD6ECD412BC09F316023DD5CAAC511839733E51ED0BDAC508DF31A0BEF8046D664692C8322D0CD6FD01504014ED47D9A5B10F710777929BAD2648F39C80AFA97507F4925154DF466F32580A223CB46FCBDF8278C46E48BABDF807F91FB28CE0EEE2DC2BA0C2E8DA1AC92A47290EE01AB1E6982BD406444EA6EE03733631BB4A41073D1A16C9BFCCC9FA709D2E16D36585A2EE0B2A647ECDBDAB4EEA3C92D90B1771DA7CC49DC8364C7536397C5337FFEFFD1B06E6350F48201B2773E95041842E19D612F50EECFCBC6D85D27B106516E04252B88300120BB17A0ADFC3192E485435923D4E08753EAFD10572FBC90104CBB4EDE893F3BFCE87B8AA3F7BE0794A0FCEC13A9109DA822F991336A0C245BB10E0B0630F033FA06CD66163585B4C03456A0D58BBF75E5FA30C6911BF125CA92BB709F7D151007A97BF82E77BA222FADF61F93FEA561B4C8DAD5A9C0167723D4EC1DD2492933DB4BFF24FB8361CD65E710D13790E82A8F5A96CFEA39F4452BDBE7E95A1C13AE189EFD21973BB1B2350FD03A58D1DF8D4276D34F4324FD9C8670F643E42CA64560AC633FF2E1669BF56796EF919B2D200694F9DE8459CBFFF55D18668CC03F1312BE7EA67C108946F87ACDCE7E437116F64A52D6435CCFC80E6022E6DE52A9D5E3BA264FFC422CBE4B5945977A52C5405A34764B22715213EED0FE871ED8A1A012F78B03D21B1C4484FA111AF13C9F014102D3F04669F4820186D9BFBF9C85F4649478338BF10501A8FF13763A9F80063BBFCD6153B6CE521D40E17461319B1086E023D0242CFC6BDEC8E1A46FF2C3ACC38B5DEF89CEBA02CB5E072A0F080A0281402010E40E0679845C85DF12CA1CBDAA4C3439A172868A05025E6437BB28F8E7A8DC8CB9B26C574FC11EA90289E44BD75321F7421D9D6323FE5EBA5010D02B530022509510349B0DB28FB01B7EA2B6A15C49497617B72FF2FE784158A548DF89D6170E441D2A0D95B596E535105AFBDC5BD16614492E0D02A2170CF84A9C4685D2ED48E712CF185D366D8CB7F48C87ACFC3F1D7827807E843D4F4D0FE8635CB909AD50FA3A973D663AFE67C8FB76A95FD3692F4D52C9B9C9D22C186ACBE216E43DEC11C21501BECF8EC4A1D9DF8C285FEECDF8814B4343439394502A9719EF0DB8A9EA395D8FC23BC0835A9D3D1D52069BD5ABD8CF29D7B645B275D743DB4C0BFC2BBBBEDF125F4011D175F055D12C6298BBC50C5D213F759ADB88F30509AB7CA283B59CE0A769486D525A53A186DF96C8E4597C130F418D5859B6CB788FD54B35B4DF61FB3152AC7803DC384DD14A19987B42364011CC152A5BAE4B3F34FCBB9BD497AA11E9F1A7E0AEA39549E637758A796A4BC415D21295843A2225C0B046894BF5187D40E18CFB4CC9F187AD63E7FEE71231D5C9FC4FB1A0F9B7C3F7C4C3DE1FFA11C6E90DC21326A29CB2B3A9430741FA40D2931451A1F43AA7817039C4D7D0DE22D1EA5A36B63F9F4182C752B48A65232EDCD581B2F9167052338BF26D386DBCFDB299965C9B5176C731D056E8536D8548FD4B62E0A89BC6F507A9F5FD00B28797E73FC5FB4EBEBFEBACFDAC076E15D00BBAE2EF2651C745C4C880CDB2155536570CDAFFBD60734A1537032D0004B604C78E8C29045F4111D16BD74E4B8F04F8B63092779B3FD8A0FC6E53A475F4D3614BCB97F4A53110469198FB21F4298E65EEE73C1873EFBC2896918A4499F03F1BBF8E45E40CB35BD452FF0B15BB002C20B97FE1AE52A9CABBBCA242AD3FEC180E178AAA0E991530609874AF9C2399C6F5E6C44910F456204A370371CDD294659D999EF5BEC9FF88B6E4487BB755FBE9DD1D62991C13B75DE436BB2E1467856438B5D2DF01E008AAD68FD12F3B9F4079FA3B0796F435C3BAEEF4361A796544C328E1F4ED2F7ABC88EB77E9F514C3221912871627B567A5774EAC268481C7BC36D15F42304403080BC5225E59067E076302CA9809B44F220B532E8A032483FEBAAAF5E6FC6C60804AC6D29AC1BA0DCE085F8E899F935E363BAAC33B9E6899E062DB326911A30920F68F66E1A0701CAEF604FB9DC58008DDB4DA0C0ED4969E79801E4C92A84030D9A806334576148177806D507F20268322D008C018A27FC422D864A287A147A087A3C7A3C389148A8B4C5134F336C9E5C01214AE2A9452300A69B0248534D8425C1A3A42A804AD04410341506E5022A11C140304B981C81849D2C417524A81D1C3E44140342ACF29B12A6D586DE3712CDA2B08E2A649D516290FDABDA44661A694A242EF670B4387A347A2870B2AD286D5361EC7A2BD92CA8125787CDE91C9DA88F38A91D880633EDF0F77403E5ABAD8583ADB79D9DB5A79B8FABA7CF4FBE4E7E200227E9FFAB7E31F22953418A00C955291910BC64B4522BC7552C444FBBD7B1B9C4E85C454BC24B991981245C13EFB95EDD4CE5EE5CEC3F07942EA923394E22728877CE29A72506E327B8D3B08246D4C462E8DCB5F139E124E2A079610D45BC090CD8EBA84A78747BF038140201001D10B06DAA9313F1E7E3FB074ABB5BEF9B164DFA091C14DC77186B7CE384A466962C10A014205392445F165B4013923F3A5657C8B8F5519614CDD44A8588D6871C35B2EDFC36B1F301FEC11CC1D01B55189E2483D9B054582712BE019388B4C487F0E71812B7D5C1979B44719FA5B913678FBA0BE5A5F0F0F200ED7FC4AA506A27CC4010F349E8342E96DC479E9AC1048CD734C0A05EB99830229BE7A30627713D28F6E6B5FA2335978A98921FCDED4E234AD256D213BE0DFF4135D6CC137D7494812F8B4F751AAFE6D188D6CE857927833016209EF58F6831F8C4FA2826C410F3D028D58410D6F6EE8183F514E9FA215EEED695E4338EA649CD2D2D60AB70D69A6405877184ED55336A9D27651C531EBF490EF32BD716AF6EF23827ABD0C2C7886A00594DCADE851F0D022E3AB1F044D8960811F4AA74C19FAD1F9E92B6EACBC704647E3EADC6CF391223F5E0A643D3614663E192094ACC6D9BD6B35F8B2445F281804F2F4A483201E0CB8CE26986E788E85AD003A5FC4210CC26ECF1416968E6322AE2DAEFA8BFAE7D7C418B225EF4040AD74476F061AC09BBA1EFAAE0F5FB95EE04B52B3D6E7D017563746695FD69B84CC5BAB61EED6930EA41F339B6D57692DEE24A343AE328E935EB7E2E243500DEFB542912C11977655A87D189DEDCE068320B6FE1C40797408104A935E384072AABF13BB4712FE37D4CD1DCB2BCCA05480897153CC14BEF53802C6A3C81E025483C9F4426204F4726185F587917FF14112DEDE0D0E4B5FA766EA982FA8570EB1B97A4381AE677106FC0536E1CC53A8B508B3364696C3BDE20EC08638D46C8F14A5360A7B52D69B0239EB72A52E20F1269E9AD5C2FFDFA834C21E2A8EF197FE666E7571EA1ECEF58DD06E50B5D2D1EF501D38AB55CD39493DEB959AFA19F5D9D092408802D2ACCDA8F4323ECE250FCCE0FD05C1C0D5238FE3C686B1FC1EE8B5B216C77B1C00327DC4A1018FAA4CBC8692FF4FF10CF193AF60AFA5A8B02BD77EF34F8EE48D18E8202F3AC8BD96B068720BA9B6FDC0B18897C686F38D0E1355DF378A24B6CAA28180B5E10A4252DD41490D880A06BC10E433BA0D65FE2726B1E09215BB431000D9D059737DA1C0B7DD210E0B8A5E30C074E83DA2E64A1067A8D2C1B46A351C8B532D8BDF8FA64E7EDC3322C5A41DCB0F507898A0725833B15C24C700771CE68E4CD33DA65FD9C1F2B9C562189E60B60B7157402D7E89A87F8F337C44126BA33E330C6874059235D16AF5C59D851472896675FB6ACC60B49326A8801AED75975CA9D9CA1A8B04E2B0698A9696EA0928DB167EF9B41D284583109B0F9942FC6097F1F56ED79CE2250324B96BA2A67DDF014B05414120100804FA474F292CB22307F5F985EDEFC38AC1247CF9017CE9F917C9044314D0FA648044B0AFC7205CC37D7E03C57AEA90D0AD362AA6611E23D20899154BB4053E921A58350CC4EC7A859C7D1EFB6B381FB0C44559FEFEA6B1462A8B8DB08D2B0EC7F8E218EE2BA052BFC293E518BA9B09F8BBD2E18EDE042415B1689C4636A25F5E1C8EAE1E33C4E548035F36CD2747C467EBFFE0ED61BA108BCC5790664BE615F494D320D5B6D9F5770E4FB56DD3C73F2ECB72957D1CE3630C9902010EB85A0DE48F861EA62AB21B6C5D94F23E6115999B056F34AB6AE448161D92ADD7020C551AD5289FD841A8E3BD959CA2F3C6F3631762FBB59F550473A0CD659462D9F092B78051866EEF66E1A845D68AB4C2AA71645E25F4F4C7C2538747C62CFA24DD159D5A9F9E52C51E557591BD8BEF8FA7364D5FF74E460EE770B9835C25493C555CF17E47F5BDE5F02FE759BF966643F55865766BBBF7982838D7F44E1D2DB702A5CC4EB99421FAEE01C34A2AC7AC30A25B63D9A3D4E5D8144287F1437C44F156BDE645D6559F6EC09FCCB5E67F0D565AE43C30EB6A46DEF0E3FD7E7818CAF01E3BD4E18389BC7C83627534EA3DC3D6BD041F16B8F5DFFEEC6A92DB6C916C8AE4F43D615501D6BE239D4B3342677BFE9BCA7073855AEF34B87BD69ECA1BB1C540CFC6F076D68EAA87C44855A7DB6F69DB2A3C5768239623F8BBBF7C76559FC8DFE9AA1F77CD2DBADF9B10CE0CEA15DF6DB45E50E3874C32C5BF8A38879057AFC3A58C987B4EBCA6E826CAB0ECB9215A776BD83AEFADFFD4A4F33DA0DD24841970C3F7E90B8676CCF1F5B782B4366FB3AB48FF62251A6B062622C90E8858B1C48DDFCECDDC2EF70AE18E85B0F5FC658B1FA185C51D4AFACF53484E23B468CB1BD295C4D59E8ECD63B8411A94E70448DE613BFA54579A82006D618F6DD8D3CD0B1A95BB1B4F551DFC8BCAE2FCE715A6F2419F023E99252CBC9005F6CE22B16EDDBF9D7E350C443AE308736FE4437BF49A62A75A79EAD43EA74C5F323FBC030CEBFF74ED321456ED760751EE682D836282628CE282E23A67D8F58281DCEABCE346A1677EF65F737FA28F721FCD16DB8C6E5BF8B08A2E623AEEC9154C01E3E4828AB68F369126865134A5045A09354B6F68B7319FDED4EDF7C435F2D344BB5D7716BD43EFC322A17ECEF06D2CE48BAD5ADDD463F7DC3BB671E2B102FCFE0EDFF240C5F3E93FDEB7DC36344F49664B43D46FB1C4CE95920E507008EA150AA0AAECD79CFDCBE297BD2188EAFD4B27FA53C717B4D9E4079D27B2AAAAD21CCEE6DD5E0FCA7AB8FDA9278C3E1378056F37DA19D026E533851AB3F5866DB1D852FA13EAC9F340C4CBB77EB6400D063050AB71A41657235CC369E821C329FC687EF510722B26AE219DF4F8485130F42C04087495FEEDFEF3FDC3D7E06C720F54827FCBCC7CA694ACB6EB777A2DEC549F455A70F9DAB51E6177650DBC7139625801101A9FAEE5AF9A1EFFE9BBF7EB0DD90F7C507E99E15E7CA547A7AFF4871F8366665086ADBFC55A6977A0DCBFC068140C108FBB072D4762A4108B9FAC01F1BD11F39EC24A214BB6459A27F61D8FF5BA52B5FF0557099AFDE51FDB45B471D14173B68266E4DE297E3C792F22D725D814A174CC07E0DB224FCE3E5F575C4D1B1BF045E1C2C6094653A14E1B1EE7E83F19C54A2624EBA4AF2E898B03083A32AF370CD770F3A709C12915D735E408288ACE482768A129B9D880CBE1B826417AC1C9B1FEDAAE520A81200E0CA2806A5E2636760F2C305018980282060223C0C06F41305D058F55958CB4656DD4CEC4FB71E34263928EB59E5C653DCDD8D692E5B675AA9BE7DB55E9FF51A3423510A9D9428F4C730B885E38F054D4C18697B69582DED925F2B0A416BD70EB2310F4504A6C166C746D81134205046494E15BD7FE7A821FF3A573A0D599EDFE090BCCB1F2FF4BD7FB127A9817794716A2B1BF2C8DDE62160C1E897CF90B1EF11E30C8683662FF93E3CC732492A880929C7A8619D0902C140371A58E5C0AA6EA40D8ED433BBECA91BC258F31029D2661B92F7EB066CE27DA28225B2E520B0A1EFF7C43D081AC4149B106DB39CE916F588F07CA92D744A3CE08EDB02785082D00D8CD4973815AADF5B2F4809C96BB30DCE39F3E3A2259BAD878B83AD8802248E3D0142880AF18C4770C6D46D2E9376C281E641F0B08ECB52D75209FA46F351A07C93AFE709212ED7D960E403D3D62DF393BA724DE2408428826C85CEA598790818E5119E87A95930C9703ADC745B71AD67CD66936E2C2A42A388E22BAED463123F6E354842C287AE1C05A92CC9EF2EC3846F0606C43FA90F924BCCBBCFE8726CFE34FCA89F1D2DA055440B092A5E0BD8ED6A8A5286F69D7800C79BB093B99F1C7E1DCA991653C1D94AC5E9E8E37ECC12302310AB5F5708A66F7E09EAD78EDE0BECFDB89AF3DF32BEA179B597DDAB63FCF0F9A3BCE5C38DBF0326EB1CAB4C21CCF3C8FF8724E83E82C3C4B5FDFEA591E5D630011688A44DA5D2B8A31F4E83098D02BBC260ABD6776986AC368E58B50A5F28D7A07B8FDC2B912CD4D5B0F3DA3686555333A4C5B1A3E2E997D82D104BD3D5922A62BCEB9FF83B747F2ABD1E2A407D6D9BD470A084B5A320C8CD116342F7970DB0B405FF909338B4FCC0F696408C1A18FA6AF11F10CA61C26714836FE10CAF03B7FF00FE024A417F35431E558320C59E1DE5F0CB2485C42F9F1540E4EAD8AC8C852F0B615EBE4F90070FCAE7B059F7372E6962C0B3CD671607EF362CDAF35EA7A76EA7AEFDD14CD4A3FC86BFEF4F15B26DCD9A9873F2AC07B0645FB4B5483F60EFAD3465AADF99D8D267E7A18F625C5F101AC949BC922E3A2885B8DA3C6181A15CCCB5D6282D71B2D23060C4E36E5E2221D1DB0CBB6A79E72582015EB7B39406F5A2D1F961172247BCB96A2043EC11005A89467478509807911FFF2BBD48E4E1266A2FF36FBD66D87E9A59ED0CEC5F1A608780B38339CD6CF85151166A3271D4ECA87C93DFB6707AEACFEDEB44895A644A54413A4F1EB1781A5D6E151C036EFE1C710529445C6C5DE836D87218867F620AC06D5ECD5B343C44A2A56DAF2BD907AEF2108DE0B0774CB776B2C4CF9D4C8E89996C99A87709B87EDE4D1F14B437EE3AA507D8DFDDC0E28EC0FFFCA8711E2E71C4BCE5F6B3DC135AFBFC9D7E64F4EFE1ADC004F5169DF834020501ADC0E6214DAF4E03F297227CDB98DF234766567EACA9A94D34B96C7B44C9A73FDEB2518A201FA91068137091B6359AD6377A1AF12D684F907AF3EECFC07887448C85C25B90680C03DC2D052B468AD595792436E44479148C65330E568B1B2A671D282B01A5125F6AF93A0411C9836110C518016DA95DED810BFE7DE9F82CAD61A373D97A492C18D527FEBD8C83ED3CCECF87BC046BC8F628C3ECB24E82887CB01FF9381A07CCFEE878BF5638FA0DE6E13199C481C47FF0E814D1EA64A877B139A7B4361335BA8352235BDC02FC6CCFC1A8BCCA51E3B10F59D6000034F0C5DDC0A8ED0CF2E5106310168364375E664F2DFB46B2B6CA7625B1451C17E8074BF099777DE900722CBC7EDE66454D15141E3F6B71B83BF155D5AC6B1632DFFE15AFE71141D446F4A9609F89C6A1E7EC65658A49A75EFE85FD7511DA9ABD31AF4FB78883EF9059D72AFE1ACB2C2D792A23231F53FA1D78DBD8FF3558AD61AB9CA0E9A3FB000468E581F5AAFCC6E33A17832EAE22DD9337921A720AA864241FA19E7B27FD4CADA2B503D1E7C53B03D1BC7E9F4A7CCC8E18A30DFF78E91DBFCFC282C758DF42CE9F09B3106AF7D840E69ED27FA2988AD3F2B52B45BD00B568A056BE7FADB43B8460D2C4D2FFCBC5CCAC8D59A72001859C277863F6521CEDF4BF15C8F7D7F1B94DCF5EA853D2B5DD8D177B6BF6D4EC238DAD88FA0D8F30A1E35E373F264E9C87C08F1A6AF2240D95AB0EFAB6A6AD6C96F397C1E0A6B929DDA1CDA3DC7782C4C0C263335B34E45953F647A77957462C81BFD33AD08C2645C08D2CC7D6A018CCE5D26E57DDAB82E330F2C31D3B50FB99746A6CB1AEAF0F83A03DF8159A9CBDB234030C843484757A146DCDC97744F9F1BB935D24A2F28CFE84563D6FBFDA4F9EAE7506A7437F1A94D74AD5FD7CB8BD7E1880DEE9F3F382F07D4DEBF02E2C5F61BF45861318ABE9FFD600E78825C21F24778D2323F9935F5354CA626BF74FBED2C94424F65919897B51E8B9D2324C2E61ACD4DCADB525208A607237D40E3B0ECD1A5CFFCE576E1125795314C7B9F01FF4FC2ABB60F9FABB648CDD77B20F44A65F566C206448199DBA9E35F25E6D2C7E62852A29564F1D17A2CBFC8E71E9B8F482DF7850A440B591F44B7BCAAA3EC9FD744466FE40A7F52ECD49922C17CE324F86F698C8935C09B6EAE44721D362DB3661129CD5DDCDECEFF9B2CF9BD39D1087DA4EA662CE00E579BBF53D2E94D39E103684E7AF69D78C8ADF0520A9467FE7F8F33515F0325A2869D58454A55AE37B2DDB7FB83600FDEE150B548847F5BA0086404E78CF07A25D9BAF88B89CD53C55A15AFF71C889CDDC1F87E7A2C138EE14A2EF8744DF4E423BC06B9BC955BA4742B660E7F89EABCE1CB213C1B02790098880ADC4F6312263E3552811FA70CB32CCD99202A6A0F7BF6E2D3CD0A859E291DD080F3534F352C0F3186C967863F0AD1258D7F7B3D2AE07E49FA0B2218A200AD0079BF6FE207275BFE9C2A0564AF11385BCBAA373B9AEFAAE93AD98BE65D2180DCE7580EABDC45CC311AA450B6DAB7D066F4BDE8C6C1C11693DED287889B772CE22E4E5AB857D0F089E78162F506C054A7AD41FA9D3D3D38EF025E083DCA909D915AEFCF2332BD4F98268772AC33F5293E7FBF7403246DA0CF9E373F7E0613C4CF77FA8F767D2FEEA4635F4A5259EA7D0BA03F4DF84E3C44B8D72384AFA0CD8E5414893801877F67F223C878DF6558A918E79DE0D5DBA71F10A4B3316CB795E54BA1CEBEEA1C779EFF3F88CC5FE0E4BC8E6A59FDC9636779B692CE2EBBB76635FAAE3BD7CF35548545802C6478195A789F2ECC529CDCCEF8B6F58F13093951419FE1A56C14ADE8D6146A8F9E0CA7F81B283DD37E7C812D87DD7D8718054111A843EF9F153011F27F190887DF5B8575C5A6479A9AFF245F3309B53D49ACF83366EFBE8F2F55FCC22DA099BC46211448E6FB22B37019A8D4F84C42AA6A05CEFA55BEBBDC4F22B889DC715A93999AE011404AE0E872EAE6F19C93FA06636A1198592B40FE628583134EDA22422A91D33B3F2E22957ABD8824F5F4DA343DC12792E34BC5A3922ED00B0690F6B9A1FF4B1F7FDE94C607282565EF2578441814155305ACC23397C490039D00BD4A90757C8BC27EBD8EC2075E964A4981F15E60C5A71BF7512595C742B3F2A03D0404833CF8D76C0C9CA6FB737E86ECD4BFEC64616A3FBBD44B8C9D6E746D0A0BE34F71D0FF76813F78F1A99A04B33E651096099D53FECE54745E6B3ACB8EEA92A6D3FFCFCD2C46ED354174FD8B5526C06118AE4AE9B167D6CFD525A4390F698DDE23E3B13D7C2E4297D7A2B3C366CABB3E6FC7A5970536BA2F9A5BF7EB95289A780DEB59C40B560C4A343167837E66FB2E0EFED4EB440EE11A148539FE8F1DA3E0F6F277D5F2BA1592C9E2A5A40BF69037409643ECA08DA7704DF00DE2F7D84043E675B985BF5D41D10B063E1EE9D9FCD3FBBBC1F7EDCD1462811E2056F1ADEC5CE9891724323197A948B40F709571C4411D34641AB86A95222434CCC3E6489475F979CE252E29FF88AF6F0DC1ABC8EE9CC9E3F490900BB4787F4D0E58D53A6A61DE5A23366D8D4E8DC18FDDA2989244FA3814FAE2AF8BFF427BBD6404CB53B106BF9F35972D4BC7AE1684349ACC75CCE802DE6AE0B62E3B277BD191608997E37198EDCC207E9009DFEF0926678A818B507D9E1BFB0E0CF2C8FE37BCB441E9407BE01B9AFA45695C8F63C692BA0C2899D99D415FF48409B4405366E85541222EE34EAF502C007F1406849346EE10190A593DF2D24B2DC21862B55E6B6BCEECFA8521BFB847636B55735FCE49B22BF3EE6263F3C2DC0CC7FA4BAE3519E216C66A632C272ACBE32B38749EE7A42B4D474D1E6F0E79377F4E089B68E9CE886DE907A880C4A93332DEC7D934C72BBBD0D44E96DA24A43885071952C24329E214870C859190469D84396AC9E324EA8F32BA455894EE4D8BCE073464857EB7EF0B7C7188052AE3304C606C4B96E6B666F80C92E0E28F41940B561B91C0A8CC5670E8336EA034D969F971EAB4EACD25C15DF95288D97CBC978E8A9829DD2FF1D094D4975046A72CA89085ACAA9EA3F3EF26BFB9AEC5BD53E0032D6B4FDFE7741D40F5FFFF1C5A8441687C347EB76CCA7ED4C56090EF0BFC764C8CA048D27DE83B8A2D94BE195E950216B1B41DA267B511E12B2AD30A0E7DC60D26A58C21075902F1044839567A5EDFCAB048D04DE406156249D1E30742EE57A821B61EAC734926CF8C9F2F80F96F2B57B5EB97264E67E11F4503FB2BDC7891776811A6B8E6A75077513EFAFA135E52873CBC82180B7A47D2D9463A8A4DC7C886F908AACA2A898539AB8DB88FA84C2B38F4193764C9D43736F3713567F06AC99D7085F86B0CE8D48A47D147A00C32E9F8FEAE8AD29ED0E30943A1AFC94A06EBE76A083B68FF5A373F365E0377D5E410E7B7F089D322CCBD9F7CE96C7A82EF668EC9D0BB4B6D60762A379DA4076376145B54CC6678A19191B48BE35706561BC95850995670E8336E08BBB5CDF8E855F06379BCFE80A8C871D7A6E6FC774F237E18E68290C7FF71612849DC0B6120D8AE38FC519926AFD29802E722466B242138F433A290B3F43B51801661887F42BD02987F4318EA76E395AFC7F0ED39C4BA487AC85247B119966E86E34F4BDE05C9F8EAB0DA485B8FCAB482439F7C8CB548A56ED576E066C2D9FF9B8C6D33E1175BB9182B6FFAB30B8FBCCCF1FDBA240F2E671962C8CACA1ECE460D64D9E3D76EACE157D3058A8D050FF4F9487BAD055044720C0B6CB430E8C939241F0B57A0906B10D18868190412BE3216B7545D46823EA35E7B294804645816004D508608F4D2C5A05D7407611BDC4218A316CD5401144533A2882E033A07899E6344CF21A2E708C8881E23A26918CD906540664C883121446DC5D635EA2BCE74F229DF89C4EF14280284966549917CC63374ED46AE4A7D4AEC59E655D921760AC15F4A561F2701795927F871CD82F6C83198D3F6479DB6D35CCB819C1651423F24705ED472A4BECD9F6EDCAE1FD3650B8BA52969B8E39B47121B97CD7933CA7BCFC91B0BC11F3D618B9124248C4D7FD56EC6837F3BD3D12F4F7174EA25C14C417805393A6675B0D0A443FA558071D822E87AE562A34574D53FE3D990BBBD3E202DB0F707D48E9BC6B88B7BE8BC0363F5C0F15C1D1A17BFABA92A30F35B2852C5E0CE3491CCECF5B77E469DC46C962049BD1C496A5FFDB507BBE3C33FBEFB896B0857FC25F1BBFED18155FC4CCAEC10CFDB877814C08DB6AA8F6F332FFEFF6673A79A47E13E3AEBD4C641FD5780C3F52C771A3AB7B121290F0307047ECAC124E5E0CAC7CE284C154E91FB75117645F8D137C5699F18C1EE71AC7A20A09C349C9DCA643694C4ACEDDD8E24A3E31BDBE4D967D4A7FFEF1386227A5A78C4CE4BDD0FFA65D79788BAE692E1645C0D2F08C906BF97E57068A35319CC222D9258F3C89E27E42985847D73A7663AA9F9A91D25C4AC01107DB961B694BF5B1BD059AD2F3AB8FE0E614B2A1756AA6FF69F08CD924B4C7DE81137E54BEBE115F43F2F6E04041F0F2A5A7D9870F86783F49AD592F5415BAC7729B79BAEA85127B4DF95889F4E4C0D87D2E217FE27D456DD01BEFEF035E25FCF7DFF4CECE9D036E678E5E9E66DD54D2294679CAF41ED6E5196FCFC2290C21E1188E0916827FD90089E3F3F339E43FF938F36BAC10E900475C02A70AB447B37C262E3132F4CA77D75F8F7ABCC11BBED0BFFEE580C3B433B8F9C04F26E05FA0C59142C7FFF00B1CF4A1C12DA40141F339D1F214229946D57C4478582727FB9A2101524F80975208D08FA4EF316F20C824C81204D201089A4D4744B6692A5ED9926223FC29E42CC934EAA24A52F67491703B7C5314A27E13489534AEF5393E3AA6D8F438104E7EA7858DD7FC9049FB4761B0944628E1DFD654493D14FD5E678623AE1ECF998EF25409ADC238F54EE69D04F46A29902E42B0AEB93BD018267BA041774A28D38AF703982633EDFFF307EC4CC68CD1933B505902FA6378683A496DEE21C5A1842197C84B21AD40674D58E836AEE0C4FFD78D33C25049C0EB03BF05E3232BCC934A0A6D23896F4082638C14F115A4BFEF5DAD8F825F97ED0581632BE91B8E220AAC5EE9F7EA93F9670C0596D9CF1FF8A7D5D86DE95033BEF6443DF0CDA4412518914FCA737D7223FBA8DFAE1D0D3E8C3C9EA57D606DB597F72CD4400AA13A9EDE75D2EDC3E1AFF23F96C83A0C59EE012298677E6779DF84718EB5A115C019FCFA1CF839225033907570BEE9F0B813CFBD3EC7F8B72155DCBF6C806864D9917FB5C51A567920A8FCAAE33522B2D5E7B280E94964D08F99CC3854A6445E1FF70236472240918A0871687ED906B70D0CB9A24991F8B6B2A11EF4C2C7223D61E0F3C7F206488270BEAEB5E52E39129BCF945D36BE794F24728BC038A5CBE834E976AD993D98223D57BBB892E3AAE5251BB8E650F3EA60329C166F078B917E2B6AAAC0F6522BE5C390DEFBBCA2FB5C1D56B9838A99BD0CFC45D1ABCDF0A5C896161E4C12E4B54750D4D866B5B8205450E36CE3901FCBCBB6FDA7F14329A668FC568C16E89EC9E2E2ECEC60BFD54A63B5AEB519E0C005CEFAFC1AA336C64C7F35DB44388E6380C51DF99F320E487F8FAF983F0B22E782A737EE06942995D5450CA09B37B57E56285C95743817312FDAA900C3E8BE95B181FE76593D67F9173602066525196544D2FD47348449B719DF84C85B64D502462B2AF47D8A2229542974E56E49C0BFD36CF922DEB73ED8F24AEDFF13E19CE419C2D52D6CF0263F48DFFD9314B522F07C970B0BCF49807BCF5A08C1A4D27B2F5ADA93DC0AE68B6EF00226E30988F9CA6E617B886426343A2689345BDB1834BB3997C963BA57D3056D4EC6E8D8C3E58F3D8D6FC298E820E6344F56D7DC6FD03D903786E7D89A897B31C4F1A3EF4F9C897F7E216D63AD8BD7F83A09AFC468A9996DC7CDFFF8C903389F93DB5D3D9706CA66606183090BEF59F570358CDFD4EAEF60C1FDFBFF2F78DAF3662201FB77866845C4AC577CA1756AFAC4F7540F05B785BE21A83AEABA964D62A1C29D233DAF4840D4A9F0B32398D50E5372CBC51EFEB7E6A7DF7F482F82E6D018EEA881F6744F8AA504A4147CD7AD84848B38E10AF5225CE685B2C44E3929D42ACFA1C5A89271A5BEB0CAE05F481BA712C4E7BB148BF27657CCE0FC140CB7702442EC5EBE712CE33901F11E9A77702E666E2F5DB16C7714A6F26F113040001B603D387DB271D8185C1AF9D755868B6572F1D28352EB37F4F821446D462483F84FD202239BCC23EDC7B52C8B295A080D062D2EC832CB658FBC677A390BF0B9DFBB812ABDF66F39CC0D6ED30ABD2C5CE35DEE66A685FCDD30A13ED7038A7772B3C4B7ADBB24BA7BD070CF2C551556E8903825C17DBE2FEF7CEB4764D998051AD45C9F1111FB4F47888DBE3A40E6922472B02915BF6FBC06C70B1D503E94FBC349447756EE80503D6FF4B47F738C351EA0AEA0F33A6585234D5C7CE8D0CF882A4691FB7F949D9EC0004450171AEBCD80E28AFE9FFA8F363E1957D23143485D70C79FF1B27725E5E5D94B7C3C0637333AA71714DD42B274210F5C604DFE5A5C9BCE10F76A7956D26200268D1D5801FE16C3F19735B17825DD034104AFD88E83228D770AE66CDC6D2313936E7829A166D4AB0D0C0B78550183A5FBC64416E058C682E3229CFAFB596FC526639F3C69838CAD5933081769D25872F2623FE9A3FFF65F03F0DB93C08885E3820EDE1BA4914E2F5ADA33C60F9507B2CDA80C496F03AD12790FF4358ECF905C30280BB120B59E5561CEB6A7F9A1B325B8B7BE9DC7C5F5AB89FF61FD15BB3413C6C14BC951FF50DD72E0E7269CC0738691AD8040FAB4298C96FD14CC111309DD37A780311AF0641B727E6C153AF2DFE868B4F0B82531A7A60BAD53E54E4E1E39AAA4F5B6D6329FF0CFEC86F762EB2F00A468518B491014384BA57CB923A7BC50EDCC86E781DA17A990FF3343AC40785FB22287AE180674A1069B0F181675DB25C1C42F35AC4D494CEBBC8F4D98C1975EF2288B08722A057751838B7AAD7569E81417D2D1A9EBE70FCBE61E555D6B52811905F8DA61A8C5C553C0EB9AAAD2567D07CA9EB16148829B258C72874D70853F44997DE8122705C42AA505B7D481D8F93AC0BA6AAA896F27C12B93F420CA9D3E839A2FE653EBEAE214FCCF0169613459ADB28BC17284FFBBB0E3E4C3DA4DB0708454FA6F9976D4E74261CCB706779F461A21FDC10C5485D9B8C83498F2909A04330191641FFCA57343DEBA99C9A0CA60AECF47F2105B67A046A4576AFEFC254FC7D039F2C25153A7DF689AAC0209F7250A26A8F2898C0119E2C9DE11BE5E4C91BBDE68AA34F027AD4CCD514A158601E80A8B2637C0500ED1DC4FFC262B534827FF50653D4EAF28B8F54D72CDB329D3F0E68C54516E5F1F82AE63A12010456B217FDB5C1F88FC39D19E595C8909A3833AEEFF58F956E20C041ABBC79EE4F07980C047B041385BBF046A29DF483228896ED33DE0884AB3A304E9262070E8E363D03A165871DA2F0F65AD15AFF8FABCC85E3093EEF19E1205229A1CEF7BD71FFD4A91D570265901445B6680A0B6DBFB391E1D8DE10DD9ABEF0E8D8C03726D53C75BFC8BD25FFA966E36425B311E755803016CCD0BF1891B87CF7291EA9453CA319C30871C7E4AB45456559D32327EEA39C8B1E3AC519688D18AFC06B0BD5B42EA2E10581412010B899EFE415ED76DA2E0CB5F4B79AB04985F76F8C065E1088654D8F7C8C3450A8B37184F7F2402E5DF13F3A9C3E3FD23D02AC1405BCF74F23DE37F8085AD8FF5B13A4B1238ADF9F6D0F3EF7A7FA43F06070388AA90E04C59532FB3FD097B4FF2F6C65D80C78E2D524FA53A7BAB1AF5545692DCA3FCED381A50482824020100804AA8775B0AABA0ADE9AE585983518A2009C3395A6071C56E15F92869685140BB98DF93F4F91644FF035C8684375F568DF00E29DCD7104E1897CE2673B3AF302124431373C50DFFEB7619F027AEF579B513A6ABC346E5A3023626E8A905B33DDB47411A5AF2B76823FC86A9617F00EABC7200E2F301F22372010E000EC94A420EB20182968948FB2B1FBAC8C4CDA4DEDF7F2C6A2BD970E22AB84AA0C2000ADB584090F6E6C069738FA721298A9066F08F6FFEDD6067F73659B1967CB844D387F6FA444DC96BC194753C4CED0E76374943596920D68AF979806A7A80E15FD7B8D850CB9C876CBB82193BA6B5981FF96552D99C756CC8A786F6562DEBBB971964BAF5169C2E764E834AE3010702E88DCFF623C411F0C363BF4C07CF7E4397DE09FEECCD01DC4D3C4836DDA389A85D072EFA0F9AE55F784B1F84A1FB70E8A2087B5B7EBC88478C97CE40480E7EA62ABE4626DFFE54A573115F5D665B07410974162FA44665C00ACA479F5870C2CBE3D845075DCFAB84192260565EAC60175E18328CBA84C3ACFDD79E277AE44BF3D220F1E723A34D2B940783FD46D2620B10DD8050436902D32192E065EB136D2F0ED0DDE5F7D38060A689E3B736E1EA084FBDC5DD0D13591A083729F685094B7FF71D617BF5E1C356C62954C33C9B5ACB393E8096A0F723E43048FBE114B819B7EEE2A180749B0EA28E9B5EC841A936AA5B45710F7A95BEB98F6F65BA3A3070A245D9A862045FC5C6848FD749477ABDF480525C9919253760E4052DD5B39F0F1DBB72FC7BE408DA3FAE414C679192627DAB435754DFCFA1579C8424ED81A0CF2085B1203CD2E355C74C41778019E1963718A573B60B6E538BE0464D88AFA43FE413F033E3574CA0D4CCB235D9CF333262054F60F42211261E5713D0CF98C0264C1D1A4208AC3AC40F9A89E80613F3460DF625E41DB98F7585651452A2FDCEAEFF5A4DEE264C6582B86FC35C60ABD3B7EBFE208D3EE350402C62E76D1E59C464C7A8C5F632FB785CE846EF08034EA338E9CF0AFC328244552FC5CAD03A08322277740A28769D1C4DE764A1B4F5A16AA5BF630FCCC768587D77792F8CF3B1B83D9AE13CF01820F7B846047E0CBA677177B52D675A6EDAFA9E0520367419D5EC573718870C7E27B3B47E1FBF54BA96661896B74459B189B1576D54413FCB0BA9B69868DDB6AE5D710E47700A84AA7568CABDEB715233D77476FDFE2D351E99F8F0612900EABB9F9EBDD3045B554BCB6041B8A809CAF59CFB60580105C52BD1512258AB6AE8D5FFF52FD192AF722041F6D0052A227904B1E386722A89BE4445D03F3351641533F09E8485402EF2489A9324A043032BB547B83ADC0F85DB6ABA03AC31649535AD83F93E6D312561D7F8EE4A3FCF7D06C1FA3D0412EB55D80B3283631E7FC7F1243F270D7949D2CD114D890DC97FED4CEFB96353626E16301B3D71C877B9836756562776332FC3F58F225D9CB19AA67AC917F67A1673556C4AFC5B56DEC317E071D9ED4465CEA66A30D3D697058EFDF20B0992ECA866251D5DEA99C732F06E9C1CD7A215AF16ABD39E1F175EA7E78F25CC647219186C64AC91F0E1E4256DC4C8B3D8F268CD7D42301DE6C6AD53844D99A97BD70A0326BCFCB34676FC216607092243EC624B7A92F4022AFABEE169215DBC5DC41032C5A7DF9F94AB5C87D1D5A24C6441F0CDB520B54DDD347BB14F571A529297F9A75C0BE81A0DB963D1AF610116E6460D150C911BC521732EE4F2B782E888A08AC2B8BE7D4A1AE01C283ADE49B20957F8267387DDFD7A7B6A646B6B2DF11B4B2C082E14150E0D8FFE1394985D5ED4930DEE3D7640071F60027990649400EA15BB580C2D053C05233A8B071EAE7F9408B78634A963FB8F6712D8757302CCCD64292658FD42F7FE871E09A70B4D8DF0CEF6279E05F7E78A035989B1D445F1739802087CB9D5DE4BDD1155DD626F9CBFE1CFADC7A5B3EBA71E4D0B6C9A503C0050DB6ADF4D92571283423B4D6AE53DB933D57BB0F1895F7D2424BE7FA78540697EE50F20AEEA6D46A443288432FD4519AEABA0F7CEBDC88759BFE8F77A445D0C0089B04FFADDAB3B65EFA0106EA768BB028FAE7CB0EBD76313273A69DAFBC57C3052742E325B8045D4BAC004574E05B288D3AEA49F78BDAECEA79936C5CA599B85A7D81D0A7E14FA117EAEDD81F921B8785645ADFE001993CB67D1A6980F2E5C959EB937ABCA522CBEFF6159F4DB19BD4A955D780116FE395673CD41FE864485D99E4FB274835BF01F7A8373F8AB3D1EFB9B1E69B4B927C0FE6289DF5B8281998E6032316B1787B7AB3F05143C4CC9C239B1ECB0A076F461F22D7D914E0DDC07B30BF4566DB4D253E50E09B63F29151A7AC68D9F1C3ADB581DE2B8F21D98091F6D108543EF4A677E3AC19A54F1D45CD519D4C8445E739B441C2C6683CFE4ADABBA718F6613479B8396AF34B03E2796D730ACA3D59F4FF8B61AB4F70A44CF42C48155561E5013E87C8374D2557E8A0A4C3420955EA3CCD6816BB32C237DBA79651FFA5A3CB6A0D471E9045E3289EC62B4C73D7948AEE88BC11AA45092914839B0B6D3467073B07291B4B372F5B0FBA388B044DCFC2F61AA184A83D932259369CBCBACDEAD99F0994EC92715C9F2F4851F4C63F9AF0F34E1276DB2B6D3773FF3EFC6B46FB33BCFAFB1192EE49FFC1C1497A687815FC64EB65F9C9D2D389DDCAC3C1E6A32D48A367C3706D6F8EEDE7E72AE3F7D2E8DC01665842F97293602119599A8FDC4F3356D244F0F3DDFF76B278A71B0385E63A83392CEFF554C5AED36521302206452F1858580DA632AD4F5E2F4ED062A3491D98F943B1C0338D6B4099B8B1674581B56D0FB8D4F3FA957D9F9B91E86795C0606EEF624562D45CCB2ED91BDFA91BD5B4F4BDC651DC610F2E101348A6676388F5DFDD3D6E8A25C6BB6194973525618D2BF71818CE439FAE0102210A68EDCAD6FD9B1FEA2551B224EE2E7F006CBEF275FCE34D4C73AA4E77BF96CA90053C58F23F2E9A03724AD8241F318E1848A82F591CFAC3A5BC5D7EBE92C6906CB1230B6A707E6AB4875052632A49209BA8DC450541314080F08000D660D4660A1485F8CA904B13A0AC189633DB267F96FB3E4399D8F12C9061CA8A78CCF86B9F267EBEB1DAA1BF9FA245063092E5D7F57C8CCA97647EACC70D8A1315A8500CB80DD6337851148BC5D406D99F07279F89CB8CB8385C4B7E1BB10E21C66D6F04B6868020D01DA020F09030ABF50483605E0AEE1FF0A8B480E88503FB1CA6819A1370BAC744FEF580C0C25898CDEEBA3DF8A2A87B1E5DAF79957C1E40219943C332932A0A74865EC6E16F7F11A84423956F1058BB5641906853257924EF1C5B991D311F983D95F1C9676AD3FD4C3A05C6C22C0CD7E7036EC15E3FAA09F6894CA020DE083B88B4A4CF020E9C7A413C810215F82E56948479B4ADECCAC306947FDF7BAB7F56A55D7F7CD621EC1C13D4E7018BEA60384248A02DC0803B1BAB0A2B730191A11A39EE780DD634F4A934C3F56A37C877D4FF0880B8AB435025523DF1EA1DEE17A56BB7A8D1353CCF1A1455DE9B0E66414E546E960EE8D5BD711624A316A749D1423CA2C8671F91BCB2D32909998C6030BE93488844C69EF984FEDA335DACA5763B3A6A2AE759243AE218A7128A78D7B5CFE0B21018206F829DEF58282690E8A9463AB6D367E7BD65340C7108518FF8CFA9B586FAB601819FACEE0B4EC25D9017F745AAEE161003C27912A64B32ECCA4AD4FE708EA24B218EBEAAD5C0320CFD975AE47792A5D443B269349577654AE108CC5096018E26D75857EB94B765FE0DD93E3A249557BE485062A5DFE5FFABDAA6A4CBB4D23DE6D333352E94999CDC7F5DD32091D91863C23A44E7A405A80E4D0D0D8A160C2A42DE7DE3777EFFF1ED42DCDFD03855FB23554CC345BDF794494D9A26294EF56CED119631149B92C46FFDAD3FE403E3C76274F41B85C64E4C78696B8B79C7E2971AA2B6173078EC2CBAEA850322D47C769A215D53195325D656DC84F1E93E1EEDCC762C4F6A8BF7B6E578A2FB807B4138DD13D6929FEADCB9675660024BBEFDED7D334DDC87DB16F1BC20EF2F631D10F2FAF03521361D5C80BF730BAE9109EA87A9B8751C6FE4A1A5C7A455F52C1BBCBFDB7AA277C85B241D070069C79A2FECADCD19125AFB0498A1B7A1F5A10BDF6119825D944DE8E59A2FD68BEC0F36A10EACDF33EC4BD616FD0E045AD0F29B722CDE6B8B7638CD21EA7744C286335C8C2D0EEBECD75C5BC3D019E1C98E0F94C798E23D1F9AADB94EC75778DB3A10610E50E216FE7655965E38B0815AF7C24545144D3811D0362F14DE399BCAF3219EF58B0F3BCD303C0EA5D01008F43C69E86CBA2AA91AA97C3EE19976A6BED13D3AA2F25248D8FF5DD56F39C6DB01E63E4662DCFA7F0A379E1B4E369DE6BAA91951F1DF349342EA30574B50E6F0468FE4048C56B0E19172EE20AF4A95DFD523646A4757B5CE1BC2333D2793EB27B56B287FC025AAE021922C417C9F84BD000A366478217667F7EB02EDE7D80BE6FD75470290C314D38BE56764CFDC5F27D33E9963331B4924C2BFBD79DFD5094E1EC6A0CD9EB824A744FEACB355617D5D70D67335D1D73DCD4CBD790A92BD740AB538866D1E939227B553B0D55C9F6C1BF9740102698A9F1058B558F4BC9D0F5DF0A7C61F4E3DE23A9CE0FDAAF48F6ED3CCDFE79A99B6C314C8094E833D8293C0B7AA9E11334A585EDA695A552A3476B30C4826CE2122147D3F769DE769AEFD26669B47B6206B5501463A4393313582E0AD0FBB93A8F7A7B0AE67B1052C2409287B5C49BD366EAD1EFC6E09E820ECFF31C2DC72BBF5116062A1B44E261FD7F18B25980E579FAAB4DB702D2E14F5E044266A68D54CF12BC2B2C0018587C63B135775ACD74D2922E119A885E12A08E5EAFA01DA8EF1E81FB9232A3C366EA38D6E7058422D3BC0B03AAEBB25FC00720DC60B26611630A592BD4783DC6A9919A199729CA6AF89A2F26B5DEB87616EFAC7F8FFAFC19DB8B51982A2170CE8F5AF2B811FE1C873FE15F094B68FEFF5D2D009151F7FEC1E02769064F89F46C010CC6BA1CAB41B57762138FF8DA3632C912461C93DA275FC1159944A36279405CCD91DDDC82DB06C99C504FAB026A1E1B905875AD55F8E2275B7676AD85385DBC56A9CAB50DC0C434C737D37402E25CE8E77105972639E34B564C7572DE2F791C5659D0131A65673CEA9FDEC558895D008BB8BAFA8A6EA2D134EA7422BB146FDB92AB7BFC89575C860485DD88BF69008374B078E6EE85F6B88B82F552008FCC6B73B26E9A1424708F4820135B5653C8E84EFA0EFF88D3013B07C3330176487D62098E62F55C8B4F05D6B0320EAFEA86095C6F8194AD5D24194DBF8B1D217311BEF4D19C54333789278CCAE67C7BDBC16C52B684C6EBDB3B2ACBF5D3BFD0707C56633BDC7391F0757B5F7691317AD9154869BA51770E62836E7EBA50198BFF342F4BFD14CF17F44E6EF9E0173E22CED226BE170023AADF3FD764E5BF675B4720BE0669AA3DE3C45BCA23181E1A0D76E26EC3A1332EC83B8847A2CE2A1C3C167C540D10259F906EF8E177807C26E89F4FC5BC0373FA836648BFACFD4C0F73A2E2288ABE3C3238160B986B20F9E3EC12B3CC036C87FFBD0FDB1E84E3C2BF375555C090EAAFA8BE750F294334E17347E08DFF91316F295A32DE99B07D5D47A9242B656A291CD48AA52C8DADFEE97B7BD6A99E6B72F7F35F28A656FF712C92663EAA4BD7341A995D805F5D010158EB85047FDE4EDECE5606D6FE9E0024AD46B0AAFCBF21534320AF41A3CDA3B02131F427269A4EAADF4B622698BE02885D88F11047D4ED018C2B0047FCFA34B81B892F82E24E8557FCEE0B7FBC86C0F5CBD8CC07C4A9DD421E65C629C6F75799CF7C88006424C594CCA02A50DA272DC45C2210631D00319E81CC73615F5F45CC89663A7D581E1D10E7AC691C775B5A92CBD606077D7E10D1EDA81F3D18BC935763ECCB770B37DCB34468EF55341E13E20842B06602F7CCCB4F36CAF8802D1922CF0F2896A86DD654A622286254F3A1CCA0E20F77420B855BA3983E10F1D0E2399E33345BB678DBEBBE4A3B9DF7D8A2E956E4B2ECA415D8731275C89F9D425CC08043080A1116DC64F5950C0D582EB2B924A7393E4DC6835EA49E93FF1FE17F16D26A511102AE1A5505E6C49C584F171BAEDAF0C3E64D55A423F71E7EA617862F4194B4413FB8027E6C782B3876547E2AFA5C3FFC31916C1F7713383C8F1C9EF729806DF93C0D2797C6C69B118BAB8086F1F7CC792F49920AB0DC2D26EE2FAD30FB3036FED7D159AABD7AFFD22133E57629DCAE24108C7EA21BE20219E6754EDBA0EA08453A421287AC1C079EDB19D134BFB7F27AF3C2DF7E10D4DC11A6EBA3E825FE2A4696F3B8927DA1D801999FC2A9379E84ABAF7BB0F509C993966D70B078484F3AE0B84278EC071B3691EF51A067938177E39D184F95F330A5FB4A7339D2E2507E58D3D9B667AE51CCEEAAE50964895052D343A7F3A4561E6E1EDBC9255FA7AC9BA9A75788ADABBC800F304A4000D10A4AC5E305063933CF1B992CBDB57EA4B14BE412BF737DAEF962F9D538571B2A33B13D60BA18015B70989DEE7BFD7E625D8947749798C99DDEFDB7A4378E90A9A778E8A8418D7C113151487414695D0DFD72A90F26405D4FA78DADEB2082378EE3ADE13C5C9B6A86D26E45E754DE2C5FEE6FE58E732544D4422177A00BC3B7ED395D1C265C046EDF256C85859737D2422E3A7560B5EEB411B660697BEF5D5A4C918E70F6A3F7C24D2CF70BDBFE6E6D915EA5BA40B90434115C734A075C0EF03DD2DDA9F5C77F1D6AA65D21B621E2AF80BAB9D38C15476D1577844AC8C3D0A56520A535753640C6E7D5424CA4B2282B577E85F8B8F77E9FFB49FFB9F5162E0A3D63B0280B9DB73B9DC659BEE0261DC912B9699EB82804B9DFA39AC126599A98B11537117DB7154490134163242E543E6EB385525784AF72D4E5B19D2142423DB99BD5F1289626624DB9F99F12DCC8B75057D20AD5C99407EB25C4874FF37CDCC7E50E98F1040550FE103238363C831E9EC55BAB6EB4195E73F8ABCDAA8284AA8188E3FC9E1FB0EA4BA316157A2C8F21097DEC09DB8CE3C773B5DCAC19E71E6D3185A47254B78029149AB922B857B65AAEA26807E87B6F95D3FFA5A5FA4636D0BA512F8201DBAC09687BF4B651E5ADCBD7A5D0227CDD20DB857CD2551AC55A4C23C68259BC44DA9ED1FA45EEF9D2D7CB63371B2D0D5733E157FB6A351186C7927C0F93CCE3EA0321DB9375EF643E08D1A13BCC19B0A3DD41E523F6BCCFA21A254776A95DECC204960122C24AD8B9D0FEF59EA960AFFFB7167670FBA2D0C31F4BC3AC0A4EFEE4FDA7C7C1D5A13EEDD5C824A60009449D36BBFCDD398E26B7B0BC2C3D076DC6CF613B1615D06A1618D124D5A9CBE118D432F525631E3E647A8E30B5F1808631529BCB097F48D3C30C3E81DCBB1F2C4974AFAB9C6B1CBC8ECD5BC486D6E9A7A66FBD305F4FF01C6CEAAEB142C6B05A99A9571DEADAEFEF96A843522F93A120909A87859CA2F5DD078685C7A8665F347005ADA70868C0BFFEDDFA31AC4E194F4BB05EC39ECCB03941E78A4BC147D702F1C50E5E248CC12E8F34555703D55EAFFE79166E99F199E3B72D1A9F1EB477E50ED08C0BB4FFC574E1F87D23BFC0FEB6052F5D0CBC719D60B06504C6AD6F97BB57B7AE51F9E0559EFC8D62C3F301C4DED5F45335AA15A9DF3D375CCC68AE55601F14307C4C6F81CA2F2AD5036BBB089E5B6D103B5E260AED18D3C5AFB4B8A01C62AFDCEE3BBF7B067B718A61F1485F15EA560E3E57779A982224E2BC3B6E37DA057BD1D7E912C6C94D71DE5C89A9480F65D7516ABBDBF6B88AE04482F6AA0043AEA4034C718864B8D19CF50E805031E91C1C77E0EBFD7AC75BD69EBD054AA6E1A50F00AE8787E71E011E5B3FC59FA01D0BF3C984D12710B5EF0242E6B0B661CCED94FD26A2917D3F0F89C879FE7741CA776E3648C6E5473B93A22A565E4BEB4D1BFB29AD69DAAF1FE9E8C4075FEF1696369657A247500F59203A0F7605929123F055B611A55416D523DA27770DE9BF67257FBF2DE4B6DE6B11185A625266601DE041C7E9F0D363773E4C16D7387FE1FCAF74BED33E7B6B3A70DCE2A2A385F1F3BC0AD17ED3A25FE2810C080EA7B7AC94FA499BD6DBBDE34DA2E908062BD89D091BB475D103B6D0E050AD234603005AD518B34905C4692CBE162E192A7238F81B592ADC2E1B8494E8C783CEBE0769EF18D6BAC3E43FA5FCED38257485FCFC0091207BB54D1D5B71531EDB8F922D8E7AC349AA700BD8795734314B03CBDA77F8C1B7C37E60F99F82503BE6DAC24DAFF47BBA9F38636430457012C8180697BCD3EBDCE02C6735FF5D05AE51F5ECF35BECAF94AEEE7424F5F7B725C28B4441BF2F1862BAAD1714DC4174A622AE9132DDE252DEA355788C4A8959087064BE2625E9DCAA18F8F985A4EF59F117C9F06C0526B93280C472409B4FB39A2ED2B0F873BC8D7D3700567744A2D702590EA009BA2F228F8EB57457925B4A8132C5410C664F759F3C7B0DC37D810C7E8C4872D62DDD09E95F526890EF1AD16622F3C00EE5F8BB6D2858694AACCC19A891F44FAA83E7F5464706E9A38300EA6B64CB0AF3F31257946A84A8CFD1BC7AE542F62C15896F6B50ED7C013202204372DFCBF283D72F142505732EA4A609CFF127FADE27AF9B351FBA82772B63D0D047B480A47398954CEEEEC0933473E631897DC609354C224F624DE8EC86D1524AFC527042F05DCD9DB031F1B4198D4CF21616F67FEB4FE92483EAADBC70A0E15942DC38BF79A9C9D611325C49A2E7E1D62B166E8077DBE97FF01222BA98BD75C320B85855BB0910D16A7C3948A75E487BBF34CA7C17BB5C4EE800E842FF5BF2BA154E6DDF9DD5F0D7913A9D59DE8C9886917E1862238E38A2AADE48434659F4E031A6CB01B0C201D26C748E5BACC3E8C04B8F77D868665C244CAD24AF0C3DF317F2964D3FA732D6136FD388A148928CD26A9EE3A746D98608802EC76AC0582AD10E20ED9E54CA4A4AFF75A03171107DF29A39BACCFFFABDCAF8503E8E9F3275D11D172BE7F139F0A36D2687A659405432A198963FD904A69D93E6843D3A4A9EF199675F556E3F89E47038105B63EADBD4F257DCB917F54C8E758AE1DFC4FF585EB11C00875291511ABE0ED9D9022A1238B4E1E109AE9C73622B2823130D46CFAD8B358A86CA98B4515EBC5FFE94CAEE2C35BC12CBAC74A3FDE85302F8438F0160797834522FA3D5A50C807267999DDC139310573D48AE7D50777B1D7C693D2FD5EED88CE6821023831A73C8ABF953DF6F1F3AD62BF6ED00CB53A4DF0684B97E6E47E961944FF396037F677EE99DED44926CB0465E8CAE862D8868952965B49D3047502C5F1CCBEEEECC206F1409F86A8B01BD749A1D40F2F1909EBBD47C8E3D427C855ED8A425E74D852ADF1D1468B30D17F467EC2F12D3F7A24E0BB24290ABFDABCF47DAE0C02DEC1D8F128B6A7A69257782D419FB18BDDF88AA24245B917FCF10E6DE9B3EC23ED61623976969B3164F06B48381C98CFF88429828E03AC728797957BE1001B549ED84BC0A4361E7EB877FB55E4BB58092B2D6E4C510C67F9BC5556FCB416400E5690A9CAA8389330AC560ABBD45B8042D60296DB776ECED1E5A9C96546D33AD0AA6EF4B5D687155A66A8511BB0C4CA253FDCD3E57D34AE06E68263EA88DD4D5137EC17F24D666F558157E5F66F4432E57A80D16BCDB8A907FDD048B41E0D94E845BDBC12F9AF407AEADC51C3F7AD934E9A2C5E28AE0E2110A28178D045CE757C68D3480DDBE268A8C92FD9CFE01FF19FE8563CDD76465170E3D300CCA8C452CA04A7C8E12DFC5358B61C9F172E1DB2255EDBCB7449B8F35734E550F266116803D75AAA113B344614901A2039EBB470D9DBF76ADA7E4759088FE91423B37CD4836F83F4D5EF2B23483E5877E5ED237A1FC86F9C3A4F495A7207337BFFD696609D7808670644AF9DCCBE6CADFB2C318574AC4D4C081D1854D690725A8921498EC7DE7E8CF98F78B04FAF47B07BE3E0B690BEB3DB779B0D19FC7BCE43EC01A8FF107FD97EB4D5445FE17A23C884778061D22B26979D7B008E494725BD5C045CDA4E55DC548AFA89243C48092523B295266DDC0C0B27234EB2182D4F7DDB2F5B7CF4AB4EDC906F5F4C815BCC3B6CE1D73CBF259EBC1609D2DEA8CF968B7E7FF5D57E3BDA5609B2CFB10E8495BC99FB384C8E18B08790BFC096E638AE773E005EAC3A185F97F06326FDB0BBDF541EBBA4AADD135E45BA5E296B737EF9FE1F1EB41FDBAE69DA975C4C484545D20EC88322A83E4F8C8ECEABAC4F5A2C0326489647C19B5D9881D30EE133E918DB0178D388284F7B4E0E1EAAE6330EFB90B4B0FB7FF9561BB9F901C5C9000A6AB1051D2382D58080E88503651A6C6219D38CF3FF4768961B31FCB86C7A071C49135D8F1F0B2183FCD92B97C007A23C659FEC6B9E6F5D041F788E666120648D126DFAA4F6DE2952FD0F8177BFC893F0A1253283B410290DBCE88E55C06E8D69670051028A259B6559D4737CB89C3E732F5784E98221B638B6918762701D0582A2004302A350CC3730F1E6BB4B060318F8B067FDCF82B6F732BA60A624B6BC1BA5E698C6B4D5D012DA8AB4187B67ECC90D88519D1D397FDD68D2D01B2A34C54AE89557FAEF9D31E6AC9CA522E716AC71D54FCE688921C80D4EC6B43C1D2E3223CFD8D67866F00D75216266EFF0AD137AB25FED5BA1E84E1BDB410239516B977E5FB896DA7ABDC500E626CD7CBFF00E555AE9E8422395156F63A92AEBE234B1775757BE3C99B5055FC8DDF1C621AA5449D6D6883FE7FD66BD5C728382616B3F1EE9A16BE4D140E877EFD54401925823C538937F9921FED4130079E57379F2FCCA363DE2CF5E2AEFE474A864351B51099E5712BE11E15EB0D348E36EFBC8E72A97A8DC8FEFD5518FF43D4E4F334B49B1CC32CC33458C3A0F07512E7BEE69A9129477992E3C696AA2238077A3EDD307E2D380D6B34BCE969873DDA29EDD2565A024EA8430B3059F23A639B9CCD762ABD1BA354EFD632BFD5E8A937DED2BA0F9524C7294F2B76C0C09ABB1E650FC98C8AF9BF1CF701116623040615F2337B0B88DF8A8D90B770A7C6C39E7E53FE81122452389E7795E517FB5AD6740070CF2D0E2E66FA4A303DA15BFFF8688B685822779C767BB553243BFF5A7AC2D51492E32447D500713A6736BE5A8B4C7C38EBA78B8E0B69E23F65F52C003143A23150E1D2F3D93F8FCA2FFB07F0D5296CAF48201F5DE8D1AF056D90C505FD79B615345C469AD9A2C4260ADA14C195F1DB8FD8206A8D87FFC962D10649DFCDF300F0D8B13DD5E94EE19F50B15EB99B08698E71737CA90F317EC613ADCDC6E7ED96CB19754CC884D2E125A406171C8B2D7AB729A7BFA546644FF09DE6EB38E495ADCE92C2607C3E4FAF3529FF0C9652431506445E83B5681B50544F0330C0D5AA2DD97E0835D22D2DB79806DEAA24FF239B6E29AD7DF974E8CEE493D3F2A0F6795BAD57B6D685AEE0E14ACF1E56006B0BDEAA79449084648621B31C3E9E8C8E83CA04291E3C3AB4CE2FEFBCBD7C2E82B06DB833D6C4720AF675402273A00179451C7662A2881DB74324995E404863A9EEC075F6C60DEFAE2BCD71A80108241C2D98CD89F52F0C23FB6F820305A3B23F687163C765F2A62AC57115E0E0819BC507FE4AB10AEF18183211A40762AB5E4D845199CA0EDE699A760B01F44FB834481AE6699D1E597FA693A4E0E209BA51F31D07B639415ACC4C07C52857E38F92576545380741A2FFDAA126B81057B8DB7811CEE8FF47B352132B7F07C5F162B91D6C7115DEA90C1A88DF4BE21B19E9FE87448F899A06580577D7BEA73FEB00ED6A2CEF719B282756462972B15E2874441CB3753356D8A139D2B3E12590EDB62A837038254879208600CD25F320EC32B64FF65EF184386798C95022F481CFA2D1E20B398FB28792C7D5A8708382082DAA9A4457495A89F6950A5B3C5F139690B7BFD0E6E05099C4996142E35E0587F692526B3BAADA2C0E63F67866C91F764BC6ABDE17227E4BBF8789A1DF0F4F93C43DC4521917E480D5DB15E33B3032F0FE6EFE9592DC2EF76FA7BB4634FEFE4903BBBF1F6FAF7FB0DF710771A84C58C0E71AC3C70A0FB84C754D1300867EC92CF333C1CD389D0582BE5E657076FC8218FA6FA7DEC29C073E5AE545E82922525DA26E6B4DEBAF538DD8581EB55DF12C0A830E8B4ED66110E0377403AEF7BB8E518F40DA6C09771D0AA14C70C9DA3DC1FA50454E53686F467310693EF299D840CE94BDF7F748F70332C5E68CFAA3E45A0DDD0B160F920ED16A24B4CCE405268D6CC02A8DA3130F45D9AA8F11F9269A32A1046920785119ECACE0DCE0BD21EE7BF86FF0257026965BD82DD55319B4A96938BB514B5872E97EF830F32DCCC8A2FD9C60716D01A2CF56F53FAC1C78F542E4E997F989B547035B5708F4F6C08B4DB122D31FD6274E127B06E0940E105045146F2E1A4AA538A17989D4CFFCF87C46BA12158311EEC07A0B650AF40070ED4817D320936BF686A44D1B6805F4831824BC72AF620500718D61CCEBA137C04B55F38D0BB9576E8A2C12BB27AE3C5F324298B7E28934CC42D15E9CA27C16E660425585DD004AAD20B5E4BACFC920AE5E2DF3CDD8F57CA756CA11953FBE648C89E7F8ABB0F524763B3D8C3733FE2AB01581ED8CF01238B1433B1AB546DA69649C87F356789DEF37EB8F745F6976AFB5ED1814E0982824020100874D77E25D0BB4B80BEE7DB57F777E5F7E541023A2CE0E007433C9B81134122FC442B8CAD10BBD15438A0A541899CC5DB8B6F6C244776DCF73062ADFAABB42AF4C89547E8178279DCAC1806F3843DB84580DF57AA3C31A32ACA9219B8A2AB3244861934940897DF5068EE4BD9EE93F3A2F104EC18B3E1AB90F89D22E15EBEA059DF2D092CD1B78D23C1CC6D212D981B4F6C3B67FFE14A67982012E079E3F58F9A3CA371047A434D9B7EECA6B72E900C3FB1BEB9FA9A34FDBB8D299FEBD8E023FAEE3C2756FF41654D927E3A49C51EE6D86DBFD1D14FB42F3D5C5A3621D47F08C500E7F04AB4CDA32C9B073EDDA8DF49B634AF851CDF191CF7B15BEFAA23A6DE7EAC82DBFA7CA6AD6362ABEAB061C76F3D7BD2F35AF060377EDB9E238E6AC046C054A9DB78F2E31B5BE0521C490941FB952EF805D057CA0D4AE77CBB1131B11816760C5C2827AAF52F34FFE8C9CB29ED231228D10BDBE81B148CDFBFD0A490D26113012B0C549951E8A306291B43BDE1FD8DCB6C41E0C182F6ACAC374974CEF56669243BBF315DDBB9C706C1CF96F8256C179EED2AB9B03218A281E75404F40596706F2448E665985F21C379FE137DC47B46BA7E078A9F92CA580F80340D5AFADBC7A4C67375D1F90CDF3E062E35994DE54C89AF7222DC0653F1B6D571C00CEC6112AB82E60996609C4F51BAB0A16DF7585F24747A71BC7F7F512C5ED8EF8E8830720DEA623CF81C1400125A16129265E0F15E2CA85EC8AE5FECC48DFBC1ADFDA0EEF80EC35784D758B45452E6C1E1228E4E9ABBD8F8370D5DBCD2579EFA00FFA32340F93922A3D3E04F819BB745C907A08152375F972AA4304ED7D642667E8F9FA4A37570B011EC11AC170EAE5A8DEA7545FC99E50C52C89FC4EFB35F4E92F48BBCDB1383131472BC1163DF856845E2F7FF496ADF0DBD716CD9C232B11617E80273AA9C0F6E596ED1FA68DD189D03C777CF1CED9C596132990D2E47E7D888F36EE1BB4B3841E51F225D3ABC9E54BCA08C6CA5A942D512DA92D0960CE9EBDE31788A64CE8F450F33149A39AD050BA1FCDE7CB89408FE18E8C1F01FE78F39A0CBC7EDD6BFC28C521589F78223EDAD2226B1AAD7DB8FCFC85EB3514F93F82C822CE85D455173756038523FFC6F65695D62EDB74F829ED42564300381D3E2C88BA72F13A2581617CE7A52B847C848F020CDA0BA4D32D10C88DFC09CDFE0EFCE19A63F88F0753144F63403DB348CFBC048690D46BBFAFA0DEB36CE21BD70604ABF8B1B8D3BD97F23A365E2E39E6182BE8E61BEFF22C13D83725E178FC92123E0ADEF375400EA48486BBBAC4BFF06CA2A6D225B556001BB71A1B57D561C2A5B6F6F59E85FF3FDC07088523F5EC10DE25D8940967AFA8DCD16A6978E7D8664770B2DFA76BB834D5771339CA3310544CCFD3D921351EAFEB584261119541E18A15CBF5079B7A19CE6116A4CF2A7452B5CDB5D8402460F0ACA2EAEA026F730D597179D55CBAB2AD17F74AABD4368E7EFC9613E714E195989CC869A5F1D0441BB3C0C862860ED7E8F405F684CF867B1B9122BEA4DDDBA958D274A096D895E03BD77170CE60D6033BAB003944AA1481B03AA970FBFA4551DEA4B275044F0C91679224718A70602DB2C9E09157EE61126A8E6929D423A9203332CFCB27D49B861A59233C45A9955933689E118C6DD50042A7958E3238FDDC5F9BBCCB1F5D2EA890B077249F460D90CF4BB09D0037D9E66E5B50BDEFA9BA287DD9D59988EA7741B48CA6E44EF4DDACFB500BFBD439C6603D7E1C4A5F5F16F809710237E5940EF675135FBA0C4C3DABBF3413AFCD1A6E5F03E650BB76434AE33451CD3DAFB7F8BD637581D11653415C1822CF6B77DFE812BE681FF39B678C505FF62542FD34AFAB9D44A5F5E0C3F35BDA14E17008A1272CE9A671CDF16B137549D70A72AC4D7F8017D1D1178AB96E986551DE1E3F577D5AFD1FB030CBDD9D52C41199739410AEBA6E8DE7CCE6F8BD4B4C6A16EA0391A84DF1136C50FF3C68F610C6224CCE8CC3FAFC969EB60AE24356D7E2F4B5AF56982ED3E531738938225C0B42CC0174A25D98A178A910E2EE7CC1DA71C61CED4DC488EC7EB048564F219A9254C9617C41AF4DCD915393E00DF0A92065CDB9185C820682D4DD85CE6F756B0BA10B988F31FE36E07984781B42553ED44BE569F46F336F2749454984E3240749F71E4A313AA16EABA0D991C070A9F6BCB8646949334C8EB85A8B54A5546ED715BAF25F30AEADFD57C67230EA7D6F0FBAB2B8543B9DC67461877C37CDDC23D89627BD848BCE397FDE6544CB92F89306C4EFB7CC0139E6858D352FE234423AA4BF4F32F8BB0203FA61803FB1073848BD98BEFA34B1DC8D685ACBDEBC7E82335971DEA4AE2B78578CAF530727B99856C41FB5C44FF40AE7A2E68677C4F0BFBE3963A40EFC152FA1319B4041A2DE768BF3FB598EE5A73A53EA484A5412C0554FB11E6304582831040027582335456E8A170B34CBCB1BBBC01F7B9BC0AFD0434862CD1A36025F0EF11365FEFB462ED583C2BAA46C9B89F5F55AF82D75C36BB2F11434172B640BB804279B21328B1917EF1109541E743FE3B8CC7B335FF9F706737C6D66184A2E7F7D23436E27F4B4CD6002CB6BA573992EC439C976EBCA3F82833E33636A369D0BA7048FB149733B9A938B855B2B41845E368DC8F32B2B258318D14C38B120C4E215ADE873149DB936EE95A46EC64D9F312EC5628720146F9F8BD945E2D7D47E1353EB48AED9F3125CDF2E51C3C7327181D611F2F7F0F295C614E901360D02759C002EB3E8F10A4CE59FE33DA70FB62F4DE7880FB3A62889FBCF62E979A83C3F8608F30EE087CD94EE1318A048B240ABA8127BA07512CE6DD88E7C742F2F9B4804262FC6E18C3D17188A2ACEFC2E6AE84C331CB82D927AB0C11357E9F4234DB96C96031101B76192AFEFA1BCCFE8CDE720807E647ECE2CC0395A99E330BF7DC5998FFE795071B719E1B6840565955F61A3EFE7DD6714EC0ECE7B72F42D2C6E8050FC26A8721584F79852D1AE967B9FF4CC74BE83A0EA33B8A4BDC93FA3139F33EBE3CD28049966822F0E7277E7C40DA5FEEC198107112D7FDF7BC82D07F04DA4AC45DDCCF87593A79F28DCE8272B4700885BA6D34D7299A82A15947AC163D9F7384D68F76A3BE68EB271DC740123022FC2471100270A0ED25307BB9F76AEA6A37A04F67EB222FB584ACE43B1E9284F2953BB9486F8E1FE0D6D6686230F536348CCBFFDD6E523C7EF7DF77794890DFF1D71D94FBB6715B71D55FE1017B706D80FFE662CCCB661856610C17A14C1030203D8B3293D81D0F1306E9C782ABB44DC5D04DB1BB40D4FFFD8D6EDBE4FADF849C1B7DA7E65306B74A700807347A6047837D3D8BC1840D708576169D08A6A9ABE7789D17999DAA45F46E50848F0849CB1084795A22479B7520A254E5A21B8C2B21987E804BCF6D43010B5FFCC1F4C47F128269AE7776694B9F81711CAEFD8B63476C3D50111B409B0B39BC2B511C9F6AA287E1998F29646AB7502B4CF7BA3FEF7FADF3A692F287C3ED470D40266A2C8BF2D60F9E0F29654DF637774785C8809145A6272706CA86C6500DC730C623DB6BEA021B3F118094F9E50D8299FC12DA0DEE1FFC7D8A9C890B33A6854025D87A5A331B6910CC346843E5772B22BA0CA7EF936AC12BA3FF55F6C3F487930FECAC5BEE237D5950C077C22088F640E34A440A4B1D569B54DF9FDF7C3E1E43976CE50643B1BD00CEE9CAA2A6767ABCF80711A6F32A8DEFA6BC7D22749F912B110E5F7AB7857A7F92ABBBE533DDC82F59DA3500C7FF66124D7D0ED5B1D85691247C200DF3463F2441C15866D0EF3513B7AD5FACC3890D8A099FFD1E9B7AD24A2AB1C587D76EB488742E23826A4A81208E1CCC8C87FBE18F09CD72CCC77B639FEF03E5AA96753DC14EF31B65D13B53AB5D3B7261944C77F5032B0BB60E29D2722D83C29AF36240B70A54DFB476DB129454965E38F0B8181EE068D79B3AF67241C47A814D83272E39FCD4A73B0C77FF63A8BA404F06B8D46D99BEA256C615950E9595CC1B9DC98E68300810EAD7A723A5BCFEC4F5C3EEC0D892ABAFC1ED8F19CED4D3EBB38413D24032CAF1B43BDDD78B10E623BE73F6AF13B1A90A5D24C0DB4BC1DE0D835BC37DFBAA043C7689C2DF5CD3AAD85AC336CBDA24BFB3B58A4957D48BAFA21DE2E194651697FDA4BEF7EECAF79C065B77E2ABE960CD29264B3F7620125D561F2328B5EEB7DEF5DFD76A2B9B7D83CFA47377371821B744FBCA1E964B3FD794355ABADA9E3F2F6863B8368809043C269D659824B4727869F6A73D44331200ABE7811831336B0DA92432D9AD720C66A4B4B62DD18D3E338BD9193692D18C07A200651CB33B6F893548EFD72797F1233D331B912B8A172949FAB7D68127356A12FFB615FD4596414B88188046D35D71EA9E3280D8397B37FCCC3BFA3F5429BA769F7E8FED7FD39AE1F4CF1AC483837A3D827DEF70B645E49E4692D6EA8C4F853CDA3BC7F2D9D5657F59F19BD7676505FB10A24B5A22B124C703156B54F5CBED1F669DB81748A86523CA4D19E98CC17FD4CB5F21C405D44EEEE33B246B1599676969C1F87AFB04CFD3A0E8050349BF1AD20B7ABEE67570FECCDCBB682EF86B2CDB2C565B616746CA76C48E3B260E5842D0A92176D025E12536919A137B138CAB91F0D16F2D62914CEFBD78AE512663F7704B024D5C96B47FF8AD65BFF68545C0C1AB494B1E6989F5D1708D0F8E7F2EF59948643A1CA5EFC7AF724B3657B4ED2D84A96B64405B3773FC5F11E1A3DDC8DFF489E064FE0C955FE7B1232AAA64F57E22AB2DBD7FE25346CA87411E91BE980A37A512C36E1981A30D2DD5A51B22478F25EC751AB8F86B98EA12B1508CEC85DC2CF8A80389EE47A4AFE9A690531274CA8234E81D12F18853A28E34580F6219FB1731FE54BD3E9282CC709CBD0A22199782735921968B27101DB45D503F6E26A1FB086ADEC4EC9237EC5B007EC26D4387A1182A5563A9A24D6208ED432C48F06B9CF3504974E73E8550FD6C6656044C3FE53AD4A72C48629DB1518DFBC83CF0A96B21C8338C263BB1BD721EFCC993B04151E2CBE28BF49202F2C7F19A0DD139AD98C0793807E4D50E3D5C73FCEB3E9115D9EEFCB868E65659E85D0828799DDC46FCBD26CA9502EAA8005D2E31C29F70B3561F4FB01B8EDB9FAA72136B01CFE37CA9C206EE12ABB92CE73C8A64DEAB984AFF693BFB09A7B7CA0CD959F0EF4E9D17B80A3D461919D2205B1621FB48FC39CC9E039008B96135C1B202F4195C302CF393E5418B6B8C19B7DC7532DAB4ABFB8FDDE10388448FFC4D52AC3E479C3E04DE0BF056E7DCA6B70C3D728BE5BB7314929CF729B53E281EE21B41F34CCE40ABE882FF4359C01FEAF2F32D440A95F029AEDAE0BC577AE57D2F6DC3DDF956044023EADBE76F76379EF38719A9085B308B4FF677325B135CED574A95C57692E5D527DAE98311F5C197B98B2F363882BFEA8CA66640410200A75B2DB596C1E79C58C37A31F17FC37E971493442C5C0AC7F0CC69431B4CE6B54B1B1303F1E94BBC2085E9F1F2FC919EBDD75B7A3A20083BA645C92F3F8F8B476D382C8910B402BC42CDE5F836B7B2282AD03841E406643B4C25766247F6C39B0B654329B8F6B9F1A88F30C8C33FFDBD4A640367643CA8A79F450C64F2B6ECF3216A7BE4A8C1BF47E213305336467C77FC9841852890C070ED8503EF48302F7F7DC7F96BD7FCF6148FF99BC348DDF060B03602DC7D40F9DA08C82301C8A2EEC697336287B8953D9D988338111AC9B47F8503B993651B2C859A4AC57061EB02D23235D9AF5CAE7E13F5FF570004C6B724C8AF75112EA18351D9C495F5348C7DCE30274401F092BED563CE9EB8EC7FE45F9A7C82CD4718664E6BA794248EF0916CE3FE67710306D95B1956D735F8EE7D0BCD1F544D9D8AB666FBDDD90CD975A9611F64DF5D338FDE681FA93EBAE1680DCAD6DDF17F34606B17C792F8CF118E893087B962C29C57985BFAAE8326CE2012A953CFA6F78F27206D624CE93591D945DDF5E8DBDF5ED7237774D1933DA4C9845EDC738B24A1B2ADA3D9CFF85946B505E98A4952174D15847FFB01F41B0CB26576D57D7866DACD6E3798EDFA83B8A2DB3821F105E93774E72E54208E82E238E6CC9CD3F73817B2DFA79A888ED920961611EA7F241FB84CCCFCB4BEB6817088A820E3C93301ED9C15E2669C4027591801449F1019C110051CF15EE4F7D5B9A2F6E9594531A634784472190DCEB2A97F95E511D0F635EF44008817864CF4F0295CDAC8C0CED5E671E81D66949E4790EA68015EC102215F7911700E25C86467D1ACAACBD7BDB1890EAEF5BA5791FCC22AFCE6C8041F14CB52E3489F0B4360734E970F622A1913BE3D903A8152B6F8588E9279E6B6421DB74DBD390588171032D7A76EE72019715A35C0603E58AFC4527B23227B74547803C153F905E4A6BAE9F34FCF639DE82F5B1A6E7D65642317A5E4BF4F7FE4D99763B0A11E11B3CE90FEA85E40EFCD7793420E258CDB3E25DEC50C7B54E448F0C3690D382D96C45A8004B01DAEEBA046CDC0204757692C278744EEBF4FA1A48D73E9285F6C75159F0793231E9C75D023386DE92D4E735F2F93A72E0F1F9BDFC06F3EDF10BB50043FD1FB22AD89DC412F4E9708234A91F1C4F8BCB86B63B0DADE8D5EF66443D5047201126D053405420C2B051AFA4C367DEDBB92FAD76AC3F5801EB9FCFF9F48BFA2FC4C649F9E54B42CC6D706887F9F6FDBAED8757A4D9C95D7C740FF45D0D0D1DCD602DC2C736D9DE2AFFE6E1D686457EDA7EF07833C78859736D04C289E5E249ACC0CB2014CA7E3109913CA676A9EA2ED37B0E22117510CD7BB6F04055C768F4ACF5E364656E1280F7B2C9DD2E35F9C98CF3DF9BF8AF8A96BF27CF1B2D38A60AB06603AEBB457AF16408EC1BF5FE1A3315BE7A5BEFB37FB5F494380372328D6E07A163AA8900EFA7E081D87EAD63927C2CC53CC795F22CF97F6FEF10844323453307B83F61C3D42E1C0E667936342D824041B50D02726F5376F6FEBAF7E446A1974A923F7E80DB1514AFE7DAC5EF7E79DAD9A1D04F30DDBBEB006E9297658713717C4F33A45FFE0B6488F29CFB8C4D1A45E602B7D5692B8F2BE805F00F2F8935D82AC7FC588D8A62D04B35BE607B669695485EF23FF290C5C24504DF8859C8899B047C434FCFB6E4FAC7D7EAB45DDB020EAD426E3DB6555B71F8C30D21A16194C5CCBD98AA5B45AC3EE22248AEE98E38DF0A866AB4F147ED50661A7AEC126E8330AEE2B77DE12D1A158361291F3DF6A3DA45E84127F1BC404A31BC74CC9CCF713D988BFE5890024F3840809683D04368DD1ECA373EC5B7CE803086FDDED378F81F8D1ACCA69080D785FD66CD13E629E0DCC7B1D19E8CFFF6FDE1681A00920A8140840DAEB9D7BD1C39283205B20C808CFCA1C20A02280E470B7716394D9779D7D3A244920CEC8314563A2F9F99884A8026F311012797F9891F0DD1D5E86B3A55F646A72A9E1355D503BE649BB0057824EFC64D924E34A70FED9A0E6EF4FBE4F6DD516818DBA00BAEB0640F7A8AAD041D74E5BB68A497C306EA27D33A82E7FAF136DC479E598358192F89BAD78A76C210F890BA80A7CEDE353DC8CAA8697A1085947AF4BF9B6E73F55E9F147F24AC8C03AFF4539867B7FA114486725414B502A06C9E77E27593626E2E0546DB64C86E42054BB76DFCF669414AD0404739FD80A883E0201D74F4E7685AF136F635CBFA5DD1483C2A27CB0FFD133D9143AAFA5D86FDB29C7B77185BEDF2789CA3A9B910391FFE67C892593215885CC0F9BC7E11B2EE37E3FED6FBD0C005576F665081B6342EDCCF55F66E5A8423C3A6DBA9B5F7FBB6557283A8BA2DE1AA363864213008B02D6C59DC1A56FF5AC0391A0F09E64C927B034636C63EC6E47ACC4C2F01F100D13932F859A6F05609907210D0A7C1517A2CF6E351A41B9224621B8D99E18A6A6C86AD583E84A56376A453702AE04E6EB9890BE92E1346501FE812C4F50734822B0CC931BE4ED9FE53B873D28A3D3A3ED97DA0D84E4599423A3977EF328196F0AA1A6F2DFCC18592F3F24049112A44A9AFF0C8B421678BEF2957B7AE5394FA85F4727800AAC4F34B4179D409D885963C90C8ADF71C57871177C4DDE824A95F2C7C42C79260A649AA05B2AA4675FFD50C1182E94CAA34EB543E17048DD03D49473CA5F5D154520D625AEFFCBF1723A6579635E2CA3AA42C346FCBD5A2FB8507539C1E6C727D45A98F959E5E0FE077EB24F8303AF63A18832538116A255E8008159B8A721BA86B0B82A2FE0DD1DEC2695C84CF289E6FD7E81633D05E6471768F37CC99B89B77B3D20731A3399FFA20D3A169840D1BF0A59E7F73F88B7CB607765B7B7F32229C4A17671A4DF437DED52D13D30FE2F5C8C4042BCF9E68A24DF8319F545BFC39F56DD0CD36B50FA6BA32CE709453467FEED3E2CF704D8F0A4A6E2CE990C062C7F7AA65DAE1ED323E6742536A522AE373FFB0B862EB58329AE7535D47AF40D631D93B6227DE9570C33E4FB7E1635BCEC56B26C11F46C059FF87EEDAC989B2F032972793E4B00C7F72DBC2AEFA5A1861D448FEC5D9EAE66BA6D12CE886D051E8C43DF72329446C4835B7B3D821B2E5ADB621A4E36F95353867A4C6E41E626B6D47A954580EDA51AE6EAAC9490ACE3147F570459E49493855EA6CD51CA4EA730A09AC3BBE7B2EEC5781D778B23B44468BE199BF55F3AFD3E5055AEA2876608932BCAAB7D784460E644C61B5F74504C77CADFC426856B1E82D3A0E4BF1C64DC35B268FD72530F3606AE34621E5C42EE09F3F9CA58B121DD1897CBB60A4F6362B44AF7A94278991F333FEA0B12FDE51D244A4B4DA150EB9B82F2E0451B97ADF68281930FFCC6BFB4865D9DEE0015850F740833E6C306A2C2587C3FBD2B0608EB6D14000237A45C537676D6CA3CFBB542C49BB7088B88CA4E0B86D916F77217C772B2EF1D88A720280804028140FA3E20E3AC67CD4F8D2D2EE0481F5C812AEBD3C88BC9CD6637B6AD4A1275D53208F6AC5C9EA181D066ED2D1A2172FACF5B779DB28EF608D0B51F2FE82F09080438901789E759A1B7D95ED8F7B78EF491B2FE6BC9DEC49BFA6420DF8A493BC9F3F7AFC0BBE1F7FAE534C20FDA5F57B44AE9676FF07690E705F219A4CE698B7BBBF25B26C1D3B784136C2C8E77258A33D5F4C55D86E24C45F17D4F06F62ECD61E63EF0A9962D37D7B68AEC25FB5A2BA06A28D25978D05E57B3BD468DA42F29373311EBC2F2E3AB04AB244BB390EB44EC5A7EFF0BEA478EAFEAFE5E787BDB4048A6AE297DF4DEADE5DEBEAB79489E7647BB879DBF38EBF75E6A7532A8301E3A1CF5A7ED7166AA18620672E2F2BF0B7E2D2B519ADF0984086BAFD1E84B30285ACDDAC070316F01F2664DA1839AEAC110671C4613FC0F07862B09D7A2746167A379D8024F1AE79E7C73747B6231560A9711E83732F6EEB64068431E2FD3BF35508C12B8A70D6ECEFE3650D3D01A7A1F183F835382F2CF8EA078B0E9418F6083CA5FEE04B1DE1E50E8B9B6513E95F6C32EF85505E5FCACC9063565C6AB3E8691988B2CFEC0F7B4AA6BC914D19E37EF26343FDA146E2129762870E7E16A6119657A77CFF2D577BB77E05B1E7796428A2C97E8ED6B04C5FC32556C46B4FF9B3AF9FD56BFEB2CA5C5745DA8DBE7F3E5E389DC361A16B280FCB29FFB8420B7188072B666494F82CFCFFB1F742B86C1276FC8C69CDFFDFE7137194E9A1BBAF9187A8743C1EDCD2018E4A13EBCB421EC173C1219EDA23702F5EFDF8C316F9ABF55EB89619AFB7FA3F50652ECB5AFB3731B96872D718B8C91C1F548801553E4109D1F8951CC67FBC105AEFB784DF557A7EF8001C60FA4C4ED1B627296911631EC3903A0ED94658F3EA6AC0BCA1F127FA312D081D00A823D223444E0CB7E89449A526B8EA1F37F5311648D67572CEA220B57839074650824980ED33976B00325C84E015AD591A04D63A41CA262E55D7CB8A9A2DAD31908F7FBAD6B2C5A0F28F1181C38CECE40787411273CDEA25AA4FD3DA9DB8D2730B0A42DD6752C3B702C6ACEC30A2E16AC56862B5E22FD44B56D816FDB5F16C17A525E1F74F9C74011D4C20A73B88D2219BAB8DAC9396B5B0A184979F91B691AE9F909F2FB39891F41C730519BEC8C0942A1C2A7FE37EE7DE41CD9A6C54A31553FFBC84DDC6919FB41AE07F34ED1DAA3D95BA64EEF6C80518FAAE4747F33120850FC8F29F77BB6FFF9A76DECAD5402D2330BC76754665601DC479E3F41D652D00EE49FDAC60DA60D7B84A887437856B1AC6968ACBB332A7689FECE4D60DC691D78F78FA95AF628E6510BC23BC0BBA7F298C27DDD429B6101921C47B2E90774BC9800BD36017A6337A045E46BDC590D448F675507DB3126BDD34D829EF7CA64DB8AA81C76CCBF2C1F764CAB7FADB771FEAB547DAF97D85260C093AC2CF9C9FDC7D9D1EBA088AF7399087CECEF0D7B0CC5F24E10FE79D3935B63E0D5DF91E93921D32AE5BC465DEA89F01FABA598ADD6C08638724DB60387F015EC59596F12AB6BD952242873BA6D96E6D1951DCAFCA5E7FF43ACB9888D041480A0A9FE1541D10B06B415DFE8996912E3D9AC4CFF0B3B9AF15CFD21090DD563543188DC5A2FEC509B00E4CFC6EACDBB65723C5B9462E9F723B1969BA193BEC47A82AA511B44C81747A6E128EEB00717146D4A67C6235C21C529BDDB5249F08142F8364705456EA92006B3DBCD6CF701D273254CF017212B3EA7D3F5FFF0E4B89F21584BBF8BF4C35EEEBF65E1BF3D33FD0F48055A901C24CC4198B9117391481518E8EE76D4586D9682C7C30B3BCBB9C4A9C15B6C4C8BB886BFDB9640A24164B99EA2C6861FCC9F887555B8D1A426E2D3499A770DF3BD29A37E6BEB15970BACF9EE9A95040E84EF3BF5FA4E539835E628B70C485FA1A0CA707AA377568D6663A0DECAC033E801E79FE1BE5E229C8532DAC5BC8F363401E70984907211DD8C2CB1950D5E3B469E0E04AB8EDDAFFB02833CA4CBC95C8C318DCC843C822281F34E500496AD4B06B11BEA13A398010FFC77A2F79245A55D98BB5605BCD40133082532B369A537D79AB9A359EDAAF20AA2684D706296F98319B090B1C01BB2C44A74FCF569691A80AD8A5D6213712DF663B89EA7587C5864433DB659BC5BE59333BA0FFEB8F899157C5D7EB22545122D4582FEC37B45849CBC0523B2D988E6628ABFDBA848AB0186DA170B28DF9AE206B16B26D694F00517B71C3E52CF54C63D22A2A6FA00E9EBE844671F445993B476355936B0B5DF21AD88D60969B6C9B46D47346E4F3F3F02C6756165B55FE3B057B044D26085943A86B1D5FF973D8EEC7FD8F1CFA2588C49231ED2D1EB11D29C87B9C3DA9FCC20EEF9E79B0E882C7BAEDEDD368A3E91BBA02467E5F81E16E6BE63B3A57A6D146512FF0B8B3944A9ECA0E8108086ED6C1A8DFC22D0281DDD71D0BC9350282F59F9A7C5CB7314948C2914685EB0E4D521FBF738240757FA2F5C7FC0BC6075B4D29F042FCB518996D22DB47E6D66FD4E0CBB10227EFC6F1D891D799F01FA39CF828EAD3F26096423A7EB8D2802E77528F4820133847AAF34E1986F1F96AE3C514D6A36B7686ECF55BEFC34490890FD2B956468005026CA7AFCB27A6509703A0820A1A4A2EDAB30E3777B633A4155D0441E114CBFD1E4B95FD580B029D39B61F65BC5DB64C8CA2114669D14E64259BFA1B8EFDD1BC6B28707B28969E7714E26A003C88DE5F22B2C340027011562722A91CF909757C49FC4C977173C89FBC3E6D4D8C67D6D89C63D2B8B61C31E6FE92719571D9E512EBC6F37DD6CB17018598CD584B19D9A05D30D60B16449C467A42610297490F9C59267717AE100C48B089B23A17DE0F42E7BB7880AA922ACA767EF4CF09B04CE3B96BF930E9E7F00092EF901AABF2312D511FFC447887299EF62E327D6E2E2F59AB36AFFA338FDFA08AE951E50EBDA8EADA125C1B9535C91E9275E90FBF717CBE990F90B3E79B3485EE565B9F857B3FA4F06FDFE5E0A5F30A3F6AE20769412D2A1C3E3689E0C2687AC9427AE6F67EBD7CBE275E636E21A9B8C87BE3FF423947375C43A37A87E3E106DCC1A91762580F10AB51A3553286EEBD855EDBA40ACD2717CC4B78FF3B644EE16A1730510442AD1AD4FDEB8AF3477B17B1F25F6645A74FB6565586C9EA7093109FC756BB56B12E2F3AA9780AB35C222D29043338D13AC1139CF7A83320DC4E6EC5DB62A4408E61B9E7D618BD223536607EE778E7AD4E22260E8A578873D38AA3CD62ABA56B011408B0588043500A87A10E2BB147F55AD99A4680C77F00507E62D45F5045602812B8BC53A5A0712B2C024B7601A82FE11501EFF45AF7760EE60FCCEC10B73CBA0AF16FFAFB5AF8018360D0D5A905FB3F070509C87B797968D0D3B8341D6EC327527C3158635B882031291040EB21157A4A6650643E9C06123CD9738BB14F566114E9747CA8755DCD5D96B4E324AF95CDF6A8ED052FC34B451D2888D2FAE9926757FCAAE31E57D09E54D614C6F53FA3C4137866CD71CAF090281402010C3929FE51A7974A26D48F4418B2C27B2E4174240045EFCF1B2D279F4C210A38B000F7DCBF4A1FA42DDA3C066D60B077EA45CFA2FA467CDFCD13875FBBB2645DE23FF95C36C0661EBAAF4049BA0EFEA00603B601E59AB7E51383660BB7FCD309F165209FFE9C180751E41E9F22C32247F0602814020103410067984FA849756F58AA6A4B7D516E0927A0C43AA1FB90A24A1030A531A00457D7783A281D151A0A0CF002A48DDD924A8A04B18C4BE2B0001564E887A51F982CDED64F4FF559563F06D20ECD744E15EB2BA6E841DC760E805036CF9CF386A65FFACE342327DA3955D3CDF07E43E90F80F7A623578EF0F7EAE0601140916444597E92096E4741259D6B56995C31225475E2A68F63B5B32AF7CBABA9E4D98412BF48E25D3C36F9474864726BAEB4F6C1A1F4CBFD28CE54E9F4BE159D09DEA3C7195B200FA855C6196A42C1ADBAD5546A0E6461EE0542CED2A2BABB945632650FD9188C876EC57FC94D476F42AE3179710E1146FC43AB39CF78EBD3A70E95DAFB332D320B1BF12A679CBBB7F5D5365FAB0A0F3D322A3034B672A7D3476918083C20F44EC8F351171D70ADCC5F0B3FF6A5104FA9847F3A47DB125E4C3DEEE56E42DD41087D6E1972E8B018510E99A36AE5187321CB835AD32A20C2334599188023C173EB647DF49A4EEA8F1F34721DA575029BA8D31ED2B32575C0A3AF2229B1977783E5A476D876E3A6C6B65BF43B0DC37F90BD0FFDA5991E4BE40E8C70D2AB7EFD16B11F675C56611A2C9C0756A5DF3F7DCABEAC0751183A8C12F137604F27AE6EAD2B165D703250481C15FAA244DC0B2A5BCBDB69F84A1DE7A27CE67BE3719DF26B40181410C5755328AA165A6FA62813A97C9462A5549EC2A766DF74F8B03D6C5A85F56C5F28B7E3A0889ECC59B7D36EE12D4F9237DAC69905DC329475205BB729907A278C767034A2C9300140305FA43BB27452D4D80E416FE5FDB709487A5EB6BEA6A4F846EC78D6BDE3DE6329992CB917FAEB471257428B7C3A25CD8A0718619130F6704FE77FF7CF02913996724B019B7EA500A56909407EF4089EC6A18D30FB8B5DF24F300C0BB016461F1E708318700A85C6B0F4152CE136DC0B4A9CF9427DFC9501773F3059BCE3A7C7C26D73936E2C2EE09A72E4EE8D5F36B505E50FEA3BC22BC415A883388024681A040516028082888284828C8282828A8286828E828182898285828D8283828B8287828F828042884284428C428EF5048DC21A5C83264FD0986AEA286AD7E0A9643B78CD7152926B324D1D2573D903DB50577E6AD83D4072C7889F9FD8D62C8622F1A525D683B962446CE263EB8FA6041FC7DA10E55270B520B97DBCB2C5B903DD396E32BB10585EE7C1426832D286FBA7E7900B1A0D644A17D1DB505CD25BA2F122A2DE8F4437424BDD0827E2294EFA3702C18D96F1F387E6FC1340DD2DD60140B16EC8AB6591458B02A645AFC28C2826D94F323C21B161C18D1F8CA846EC1596F453C3E370BAE3377FBE6585BF068B799420CC16277DF388DBBE9CAF11DD48527DA8963FA0E5BB4F7EE296C94E73B729CBF08D49DC182CC674998C6E5C1C33FF3CB95B1A0170CD0FF0EBFAF6AE48625AB896147DF3D1474FF5669D95431B25F93C78F75BF40E7040483CBC79A02998F85D3BA2785944CB2C78CB0A9FB025AA843928D2715D97EE7336F55792D8E19E4C4A4A980D6A14BD92FB910534B371FCB7F5A7016CA468B8C866F97ADC0F09DB65DC2D6924849985560B494318495C409043010E940652F19FD1ED4288982601DDE39846B2A41BCBA373485C9D3965EB8CA860ABC4B74C642CD9C3680AB460D2A25792C6C2FB2A095FD0433FC4047F06E42FFDB011DF89D0E8CAF257FB5C40E29C878661F829FAFE8B6304906AAF2BFD5EFFCB1D70147932A9EE86F82DA4B3B7E56CFBB5D045C30B7F35BAD3FBFC8E10F2151AF9F04ADE43DCB36ACDDCADF2F10F0D1E1ECDE98F85F2C5B08BF742E9888D09541A7FB6B100BD5F381FE24411E15B45D975B36A8B67B243B00480CB1BF2B5EDD27F502B68472955A457F19C4EF468F6A427AA7474BE188DFD204E03B9A10B584623134BD4D657565E513C671E4A3FA454A56800E575251BB33E11DFD039EA5ABA08ADD33A3012365CD59204D5AF8ABB3D9FBFF181C7C037B045F84437A1B5DCE952180E16614152E543B27CD3CB1309BFB95757E1892A9FAB703EF00472A442398ABFD4EFF5FF6BDC5A484F06CA619589D936BCBFE668E8E393D949BEB6B5AA40A514F05E6FE0298E13F3E03D9597A397C5A46A00E26FDEC28ED6AAAA77EC7D8D1BD451555D4F15FD6712A44E31495B56941B3ED2307D31EDD125A7C13A7035C971A3FC72C3366A19A7F4B802F8CEDF30F2F2BA7076FFA1E61FDB55971773B47D907E4E25D041E544100B27CD1FE692F02A43778DACDBCF3F193A0C64FA4A423B04E8A6748BF7392734EF3CB243EA56E2D69A5F64471AA482535B04DDDBF68D348BC1425FF1EB01B29BA9B8F7E0B349A7A1989D38616C92C8A8A8A9F07ECA692B233765155A1C376E06E034E2891E5892EC3CD870C0F57C88BC448253214321CBC6E4952699799593D701AB00AC5933AF20C04158519EF10770663B204AB31D9B9468C7DE656C927160506099D0C79CD9F2E16E442C125DD0519C18480D31B12FE0C61A53AB199BC928D4464754820EEFEEAEFD55D12FDCA3D3842A27DCC4019CD547862C3D9BE116946E14758890278CED0DAEBA99B03B8D86B29AD3F6D5F78EDEF3DE9B41A726B328F3FF3F37C10EEC0F46B74DA0726816F0BD8B642304F18D486D53A8B7A1850B4D65A282AA89706D40B03FA112ED6310F8B30AA8487648664C000CF63D2AAA4114EFD3ECA1C86F6968866316C6C7B9B765C05DC9EE5362AF3798FF2602B447DBBC905D314233605DA938AF9BF59C1A503E639617BFBE3D5391F03584B68090A6763CFE3AF1D727F121EC7DB30FC4A08040A43BD13499DE8A898B248017AD14E43E627D358CC09268A58C96AB87DDC284355AED114BFBA1887A1B31E37AB3623762F16970741D10B07BEEBBC2671D51CD5C21362ABD552CF448C9145185A4587AB355823260BC79A4E01BE908A0A77EC9E56C69262E71CF594CD9ACB2D647957022AD0D87F6AE25CDA2DD8356A6D204DD6A1A57F483326333A14EC69E6F0DF0D455FA65A8AE511CD01C5FF411F1373BCD1DE7E1620C686EBFEAC23983E451B009AEDAC767A27717646F9EC48C3D6E1371C7B747291EB675A39481610A6BE2956E03520A9B08017CACBD2A17246E2F15D56E68E9534E739BAA3A002C4FD0C70B8CB60EC9C506D9F97CA40AFF81FA64A728D442B87D918852B437EBC7E9DB9C0EF0FDD09C342FFAEF3E201CB9F6E27E55D0F8E7D34A39D6431A1CEA084E832002229F454E1AB65689093F0F7393F954B6D23780BF04A22C868F860C0EDC433631E8A0FAA7DAAF6DD94CAB0552758CB4194989DD9081098136A5036C5FE0CA24F6D5E054F4D7E9693EB87BAC771221131BA76BFCC071037A57D09E607EA5223365F23AE4E506EC96234DC66EF1F9FFF285218ABD948844F546A40CFBB2899F30E020FFB7B38DABFC3EE875CFA3001EC7BE3F8F9CCDB45F98ADBE367363D354659E42A7D2E91840ED7A65D1A3F80216CD214AD10B4232E67FD32BF14C224B78BDBB0D4BC43D9F848EF814D3F640C9B2741B502871847E4337B71E72DB1861088022478BBD150C3E0BF7838C41E4D5C931DFD527FE3E2C63EDE3EEAC9AA3BF5D1D1013251AD85208D89189314AB0286499679B780BB9D3062C5960CA6639DBE0F3EDD2A5FEB0D833CB88FDCCC5D28F47A7A86F27B9A3513AC8AC3BA3EA5EB842C3906C77886C524938EFD8481203DC5FD8717853E893C449F17FB358C1C7318A3DC1CAFDC5DB3E7A6587EA376C13440ADE29B998F618C3C58A86A9B78DDFD2444DE9E86E689D434CD361C071F3FCB870EF2AC83DC653A6CC062128D9D608604D561716B0E3A11AE7BA8E971A236B3568F736A0C8AF6913E6D36460724D2992EC3141BE7835CCE951D7C8BFCEF895DEFA86FF1231FA9516C4CFABB9C5E2DC05B5106DB4CF950B26DD12E61EB68AF6222EADDD07EFCB6579BF543B8AEBC062F5B9A2122BB97307CF479AF575A93886CA04E1F9BA2C6BF8E0F94C00C55203AC1ED001481E0A6A0031BEB1FC26456AA7AC32B4B2F1848EF6CFF6CDE3BDE3C3CC8015B2F1817C706DF4FB3577CC870B8A11F5D8BACDD05B496EC21A2694691CDBC8C3A9F13855A0970628E0F68695C2DE0E19F9A63CC713AA09CB524EE44ECAEF635E2280B53181E33161C6F78E48153C22F56DCEFA5B5048828C3973F2CDF1FA428CAD8B3610FCA9B390E8FC25AEC9D28CA5D6B4C01BC6F6B1818A4FC9A63521ABD2B452C573F4F384D5457AA3B38A6942A026965E646F386D0EFB7E95E971D22A8F5BC82D1093CDA28391A5C21FCBFEC4BC1E77C584010C43711227D71593BCE6EBE7436DA850A44FAB2C53DC93B24EA3F7F32B3212EE8B36475467C299A749EE471192EE82A5B44D100700B31F4A8C6C8C18EBB0BC4669F438D8CBEBF7F38AD99BBB98BECF6765531FA437BAB931E1A0EC51864799897B1D8E7331D42D4AFF2571F7C260770205D23FAF09558593004A280EAA9C3E8CCBE35D104CDA266DCE9931E2F242A697C61B39BBE13225AD1028A37E0438EDCF1AB896650B093457DC2741B0FB3E341357AB5FF4E85BFA15AC9517319C6AD37A08F3635F211CC126A1619667E1E48E8B5EC6BC182C8BF536220D48D56EB70840018F0AB5C4650C7E3B8283AD70EA4E4D31D8BD4DC764D0FBC55CC2A8FA6553FECE10590963A7B1BC38C0819BA0421EF9CF29E872C177E88F53E600DC09D07FA3F9D0E87E0EEAC33F99CDBEB15D42715D7B59010363AEBBDF67050D4E55ECB6EAA4412952417A3308ED7DB3595243D3769467C2EE2F28801D22E6D8F439B36D0FA6203DF9BFB96EDD680A347F38211AA8661B81111C79AE994895EE0055003BC6646EBE91DEA8B35799DA0F12F9835378504F39F9744CD79DE8B4D6F98B57E526D1C41E540A7A0F15696A7374C3CF99FB5CA1F32CA14A8C7479C8AD2AC6E81261ED6E47ACDDB170B70C7A52E6E4F8111A3134AC0C6A857C291F233EE168CD1E460BCA084738493F8022D64E07F3711F2F7D33079C084A3AC2710AFC19C35F9D27870A33B551E643A9D40A1148597DCAAA0952B66D1016B0041412010A8B6DB1B42EF7C3FE5011968BC03A1DCDB230DBEE7C5058F20C6FD1C538CCDD6A6F2A14316241EE9E856BBE4DE838DF4D99D5EBAB1F0DE0F0A35439D1DFFA6E4C6D06FF93EDF69562256693AAE2CD37D0604E34517DEA7FB6B85ECDEA3182230BB8B12F815B22E8826706E0DC8EC2DA1EFC1EED0583DF4E9814828454C679FC911EDAD776C2EE625A9212A93C47C42938FDEF242204401E980D99ADA5DF188E9F7101166D5C8DF6AFF68C8AB5598B9B4A49936CE540A42015BB463FFD91F4CD147A7BEE4784D53EE0E62E5523F277F14D962D418CAE3B6EC82677CC59674C6E0EA6AAAD6AD7F14154C6328282D490BC6DA9DD1C1F67E3BB83B4859D662ED57EA5C66FBDA0C3FCB940DD348073BC6A08390A111133D4AAFC617D5CC9ED149DF5163F6A69BECB5ABE6CBD7E823212A15ED52CB4613593BB30CA55A07A5B3960BFAA5E4FCBEBC345ECD471B535E2B9D6CB98466F87F7A9D13956B8159721EAB1F092CF46202983086397B74B7565D994E02056E4436378EF5FA82592086FF80803AC1B4763E7045BDFE07C12B7CF618028DFBB572DA2FE9092C4A03B78C3E5A4C34633D9B67156C980DF1E79E151D7768219F9193FAA12502E24DA3DE5E2DED5E3C0BF377EB342332F9440ED407E5C2344E8C08DCDCEC9192E039C3338E2809AFE34FF2E7E0CCA615F3E1221ACD19B40D6BC3CAAEBF75DAE6A142692A979925552CF5C3F7224C6D867D76EFA1A693471540DB65E5F98A5A321ED7E7F77A6FBC943CBCDF6648C74F12F63985E97ACD2851AB5D0873C0854050ECA6D8F27571D9EFD1EDEC833F6A9C296A35A81DEF2A0380EFC514BE87889E1D48A420280804028140591DE79484BDD1B43C8F57A70763FC18D1342A266DCF53ECA2E38539A82A1CCB8B348D0AEBC072B3F21DDFDD254C536B4694BA3D8A590914AC943E7834308737F48D8ED139A8967B4032BC4C36286C4C7253B1DAF47AA8FC39EB3760E657E6F940762D02BEEBC034C90E88BF3265A8243539101BBA7462A71A254D25AFDFFD81E1E0CFF9EC15FC3D95C7861596E10F914D6BF2B85FA557B5FEFF06FC3497239549A108A3E17600AC11AFE7A5F0EBEBCA31C7E27710A33F9A025532FCBEB078E8A5DCE41FF4C4A6290AD06472C43A265CEB594EFAD7EF034ED0DBEC6D4064D4B37DE54A72C35AEB2D6956573B987D4F878846F5E82CFF5D61266EC9D56590BBA9E31E8223AE55EFF1BA9E95613080818A9AA6F1FC77A6B99E8CD2DCD8E44FC9EADA6DB5CEB801392A1F2EE8251EED2400D1ACB884B99A6F0D1D5720542F093C75EBCEE70E8A614FEF24A3BCBED3448BA3386006F630892B22E90CC67AE6CF486EB3F3BF3F63E1E8C5378A79E55B0CBDDBCAFD066FB789D4ED15E02BCB18876D52D1FE5FA7C9ED7F48AE5A9F69687BB66FA3734028C48FB6F911D48F02ECD1F05AF78BD525F68CEB9F0F3EA3B47FAB0FE8802B873AD90C7EB55FFF0240265E59F23F06CCF4AA38193A4C6551E93ED7D9DE4BE1ECD4176593530E161E7C0F80FC67AF47C843F34AEEEF73EBCD22AF98CDD7D87567400E6D05312CCA79AFBFD6D53EC2E5945921D402B13794CFE51F200B59DD67AA9A1A6539C8732A2EBF5DF66A4E271898311F415573E6BA69E7D1D948B11196FF1DCA98E7C31704B2363EEDE46ECC70CCF718AF228D24A9F30D6AD5BB015878DFAA6F190CCC4640D9056FCE7A83F79339EB33D2115E0DD902FC68962C293E4FEE88FFFC0B757B8F91E969BF2A010C4DC216EDEA98734651CBD5FB835D11A9FDA12303B5FF8D1C10AC8326F849F9E788BA54713D93D82502B89E8F8DA0E704DC794BAC81BA45DE2C54C8BA1222634DD7BCCB7425AA801F5CD3757F4775B895D3A54A64C304E8AB8AB3FF0F4A3A1E76AEB6F22D5C746D0EDD2E2F6C9682721AEB924CE52888A0C8020B5C7972F3D8227D0613FE8066884F1A84DC425A3651BF7C5C7CFC88262FB6BDE50B6F1FBD9696B9A88765F9980E860931E6B358DA1B9220EBACB77E325486ACA2C971E1884C55A3BD42085B303171D49310A4F7A081907C9E0DC06983F69671FAD358514A0AC4CE0C661FBB6E87481FD4DE1BA9FDE33CA2F1226072A9C016AF0A03F0F66FFE9EE0C612239D8B474657ECBFE3B355B131C91554C80DDAF86D365736077BA5460FE314A97E819D8D80C56E51C8FD029DC43F27B45A719FB52E5B1908D18077AA81E9766F0C6A389C36B55C23A5A16C78F488EE179CAC524CEC9B59EA4131409305C9E6E299DC8D78A19D265521E85FCC21F78698E39E0E4EA23A355D1BFD80AD557E1B94A46A035A727086B5E27E24C65B2C9A736071CC447651AAD9A7323C490A60C96EC110050CA7442D2C7E3DFC3A52306414CF1B2C47B8376D1BA2CE28CE32928847C8A8A704100F7F8DB3FBD23BF45B403ADF4E49649260F9383791EC80708E88FB74C1A5C90139B8618F50769833A4EA9C2C82798D8E1CCD4941DBEA990476C6860B1A2E013AB0C20E3CA6FF7E22136F3D150116D67481491700A2AC16F1289C8DF14D164B4F5B8BC696DB299A62742A2240854F07823DEBE9EFB5F87164704B2FB353288E34197D951B486170F615F2E383FCDB9B9F4AAEE103A84BE5DCA9FE2023AC726AAA33FE372474F5EF1529AA519CE9C634E9161B2D812126A5776258E99762A06FEC65546915CCEE1796891833BF853D6545509C4BEDCA591FCBB01F02CE04E5A6CD7EE2F3C89BB6218A702ADD4A8F870A6F456ACBF8CB767AE4474CEA7B5BAC1CAA5C403AD35A506F9D3868E7613E7CD7CC4F06FED920CB97956866849241D891F2B05755BBB84BC7B3D330B26A0CBE2935E2C6E43EE4B041490F469C8CF43BEAF4A58AB785F3C1ACD028F1A89AED28C05830F86331ED3F6325DF6EF9AFEF0F80BE484718A2CE096096989DEA976EF9BB55D05D7D642DA9E1FF673C49F778F3C3982DD1B781A279807AB9E877810CA608157E7F846B3890C329C16CA07FC3551F73853E2EB3C8B9EBE39576FF3D901C61A99F708DEDEF362CB3ACEF4731C05175F95EFC14F2F869F1FC32B5A956C0722E5AA964D3EBAB2ED51D8AB2D839061CE265B41F4B64A0FB9661AA2FC3CEF9ADEED64C74E1450328E6266F32894FC175FC947D720A24E823BD490ABD8DFF98E5373D0D197F24D278FD3A8F48E05AC46CEB8FEF960B4022AEC6291B2D6A5D14FA1548D523E75D88EA7FBCA21A1F56F4BAA5EF44C83FC6B0998CA0DC474BD049247436E156A9E6BA41D78B27ECCBDF4E7790EE8082D3362A927A01BF0FFFC21C826B642CB48FD8E37F17CB8BC236BCD2E15AB6F5C07787661FF10D15F754664B5B05BBE62210058DD491BF9DC9E79FEA11C713B83C0EDD9454F9C40CFA0285E621E83384402F18F055FF723A695ACDC3EFCAA44FB07AFF4FD375F9E65DB384C0312366956E595816C090EE82896AA8EFC66E39C9E278287A9B13CD715ABCFBA29C47AEE28C6338D782BF249EB6CD2B18ACA7A32B04BB85A021242E6D984A6D34F47A0BCCBF4AA8A8924ABDEBB812137E596D72B81B0D1857E47607B84F583F896C23BBAAB73E933B96E2AF074B98333677BCAFF9F9D715CDF5CDDABA034D00BC4160719CABBB549388E20398C08B942CBD481FA3A115DF8BEF37F3AA8B533DF6B4F15376A06B43BD79A81CEB6732BB96F80038D821C5A4E717C343D84C02202F4CFF87C537FE6A4FC67450A62A9C4F36B529E94E2EB742E80762F5497C893C02010E7C3D3D74BE679F6FBF0F7F56672BF9A61C3A1DEA953975C878F7CDDBFFDE570F1BB02AFE363B5FFDC04DFADFB21895EAA9F610C9B42245C306BCAFC75BF1BA50A90CDED43C2494546074B5A107F72EC42E59B8164B6ED02A10AB1051AA63EC425B941E4C51F5020244FD5D114785B90C11EDCDA07F8798088C855BDA4AB1B8EF755C587A5468BB0F7F698B79306783D1763F7FCB03087E5C3FDFC79675E764F9EA5D90FD0CF538013FA1AC312C207B967F80C7ADE582931A9208593104F1202641C7AC886595F4248CC5F8DF4176CD4ED41CAC5152D5130732B7686AC7CA3679A575C23A3749A8863EF97ECC577AB345C1659F92C9A5D91D79419A47E2C974D701CF5AAA7AF4CC42952BD99C1E7B20E01B69740CA2EA17ACF13043DA41DE1A4A9FB32FC1E864FE928A1826048F1A17D0818D7560BD9E61E1C7A807EF88E27AA9D2F2BE1438D6DF6736A2813C47DF1A21CF835982EC3EC2BFA5D9BFFAFF82C0723B5EE8DBFBC9C3A9B5AD71F86CDA91D1C350DB058681EEA67C9C1A98C3DF650471893FDC611DA9E096ABB4D8DC9F40BF2655BBBBCA0D2FF4BB8CB2B66DEDF1EDBBF701577D0D2546FFDDE858C6E6E403F0D83EF17F1B6698C430A8649040453C9592C8FFBB37166C2DE7671AFFBD6AA47F0852C82E02BFBBC21FDED236D39BB55EB224B3F25C9391A076C10AA4CFEB1A9D5CE757AA3904AD0BD477B2CAC90DF8A92B4720C8464816D6FF6FAB925C2031A2C872EB1C85A7B809B99CDE7EE5CCCAD0FF1205E1A85D89F84D44220BBE4C6B7A2A9C25366149A45252F65CFED5C3F4C559274E3B10F2DCF87479C7DE9E3D259F79920F037CE8578FFCE0276679F5821E89361A2113E852D0719A163A4E9BC2AB130D34BB0E04C76E03D28D24CD823A2BDAA3C9B89E9BFDBC222FF965E8F1A878523EFD59926E2015D1AE6BE31D38544927F7F4AEB6E564969656C212A10748B4E914A5165BDF889928C33D081530469317A92DFF636022FB64AA9BDA0DD18154EF13A5DCE70843D932F2E9F11DABE2B6E8E28C0A19A74D69C35DE7E5F2B5DBED961B418F6FD708DC81DAE6E9251EDC18019F1CCC11C168582404F70E8CF45E30E0E09EE22BDA7E5DF568EE2C93E947B08798ABEAA52580D7F8848B56B7E1A3C10AF0985ADC5E6CEB25AAF46523F5CA958999401D39056679D1BF8B80FB37F2827F0EB95F84788DFEB9CA9023C8C4B0F4BCACB40F0ACD1B9864776930EC956B5FB383D8A353E19138FD90EF6C6BED8503E4363E9839C232ED1CE8745D82456CA61BFAEC7FB174E31E9DDD9C4FF75F26B800F9F76256C8F589B8A35B420DCA5EE8EEAC669A74CC727CBE3766ADBBEDA6668610430C721F21DACBEC528B677F288BE0164D0F12F06E9ECBE1EEA70EAAE132339EECF7BDC0D0CF454D526B4D4CD49F377D944D6B257DA5E4C7D749A65E6FC1218BA4A11A73C2FA2243DE5FBF7AD14EEAD6F739AD24EC8F21F9552BF08C428238579FA72EC1C58CE8EC60E76D5B25B62381B348FAAC602F1C683C612C10A49EC46DCEFF44C719575FA3A93B6AD5E6DB70411CAAA099BB2C800BC82207269592D4D55E9E9EE3CDDFCE73715D94A25AC987A0D6C10251751FA0D67EF77A04518812E1F8B315A6C7795796BD5F771015E21D4C24D9DF1A047F91B01FED98D5EEC07E2E926C6F028ED365525CBFEE897AADB4799CE4AC2E2B0FAA72D2BA4EE803FF8B20C17153563AC07C202808040281402AFA72D0C08F129806041D0ACB991F7A17BF65777B15719A8DEC0B344296EF04A5DFC23C3750113EB7FCC4063BAE9E0E01D019A794B5A83F327C5535F238960DD86F2D22990B1F13FB7D990B7F05EBB7CE037177FE34C9EE4928FC6C4707566FBABEBC6E5B82EFAB629C0AC0D9FAF0B9011E89AB349450D2BFDEC1364A2FE90F5707FAA91F5E7F2B1E3F966207893218968A471E092AC858EC00A1C61E9C5E49539E1F67847398B17A22A334D807AC0EB1670A319688F63BFF5735EC27C010118A3124E1925BD58EC6595E4E0778E863878CCE5A7BC5AE12C4BA139881A9AB055360ED5F3486079E443DB8A9E7B6778CE58DB920AA70E63C08B906127A07656D704E6BAB4BBBC56A9C26BC5E3129F529B7ABB273AEC58938D7E697D07BE093FFFA3F643DA97D5E4F8AD3C797EAD636FA72319CF68791E6E3B248E43A3E648C17087B04FB8683DF0DF4699C9C89B8764CB92FB6F76FEFCA904EAB4A707C8DB0D63D9DD1A3ACFBBE78B7E4543D5F8D3BEB15BF26AD2550256F865EBD0D6237841E9BFFF3924B201675B391F78915B2219AFB24A9DC252D4EFB18B20B62D4B85F2A4049C3521630974DBD8FE47818176B4A57F4D9B26BCBECC7F976D4CCA7E467C55CA8C7F8262FC3834D2DF8C2BA2F2265314E8A596C5892B533489A0F4F79E6DA7A2A38E2546F97D86D35ACA05C95EC7DF8EF71D6AE779CCF5F7E3463F0AAFDBC3AFD7AD3638F2B1C51C2ADFE139584A453F02F611A8672625E3337EE574C5B0D8ED01E039CC8319C2D4053477FEDD8F67747FBF09BBB577C27CE0FC1913F7500E306441ACD6829F15002A8614F04CE1920A831EFFD63D2A0A77841CB734FF945DD8585F047A43E407AED4707E2E8285061B01C174783F3321AA6B674884C8FA67587695C3CDF089571D717807D79207265E2CD47E62D88BFABADCF121A54BFD9190CBFE214416D9782A127FEA0AA92645AC59FF59F4F25777EF946C5D5131D815439D6846D248605A6E80EA8D96316C70FB7AC60166C8B0AB7E7F4A0E45017D37F53BAD7DD89FF5E31225441D2C11442783568B8FB03A62B35795769C2E70945E8C60CF6F1EBAED103116329ED6D37CD1FD72684FCC63315758670B979174F68242A6CF23D94432AA935E85D5A9D5D4E6467EFEE1AA08173AD3327689FA582B83C2889A19A4CBD996160D06DADDC6AF3CE147F2C5EB218A5F2FFE50082552475892EB59436961CFF74456A83E51E91F73B1D6AC3C501699502A24EE9BA4BA29FD4935F304F16657F30A360A153F48201DEABCAFAC4814DB1746C23BCDF5E3C9A4EF449693782E394CD8F8A09CF20EC0940CDACD9C21391F65F571E4115F696C4D918C7FB1516FEEAA8CAA68DA56777D5B240694617214F2226E976EFC2D457FAABF9179F29EF6ED0A3C49933FEB3FA6984E2A4C9C04B023FCAF1D3B2F5247AFB3AF60A951F4F7CCE1C69FFF870CB26A8587CF4EC56C816183C63F3B0BE1328B40D704B021C07B50EABC924E20BE91E47DDEB3A92028C2844A23791F6199BE410DA48DFAA0EB4EBCBD9F828F3B04794997098A2C15A9FAA549425333AAF2ABC1BC4E5F16D0CDF3F95BCEE7D36E08111C03B506CE23ADB9FFF12944E933037AC9EC00A891A206C064F90B6C13E6DE81E47EE16AB0B29E9AFA2B3EA6E9BECCFEAE3CA45E96EAF0B23DDE37A4D266674373166B965DE9794FEFCFB249B45980D7857CF24C6C751AEE29591BE4A4FEFA2CCD324EC26AB61E0234F54252B55AD0928F3F2959179444FA91659E96898ADB630175BE130A9FB878D323AD118ADB0117F8F1E32C2D38A232C03BCB819E179C47388E70DCF2B8EF39AF062071C6D19E1C5815A611E0FC6A4240B78481DFA1EE7E89FC1E96D848AFF3F0B8685D5CCE353D1AAC2F24F9BBABBC3DFCC1A239FA82A8006F1933F250DC427429629AA6524784977A83C71D7269555188EB19FCC51E7DE95B78EA362F6F10C89164D482E122547CF86C14A7A578F42078516F3B507CE108AA2D1DA5D8AEC2428C009C5854E69CBD996E25A82153959DB5ABAE2B5840E7D5E88ACFBE5982F53FF4B6C409AADBF9A044B30455DC7FCF0A545FF71D19ABCB0B9D1637F73E10D180C54F98E4E115AA3E1C1647DE3315CD93AD2E90E79A15ABCE3AA5A66E3894730767995F82ED660FFC148979D957ACC2062E7DC883F1CDB06FA97502AC9542770C3E0C9794C414B603659ABAE1AEF8902E41D9D8CEAA7A3118DFD657AC39AD23C83FB13ED92440DACB2F0481D2B36F6C07480DFCFB9C60B0993BDF0ACF34A3BFD1A5BA89E9A72E8B408F1C699AA0C6F3D3E08786EF15C8EDEBE93A2FE2F0C3BAAFD9E6CA1BC7B796B22B1E3C012FA31BE5C7A5FCBE45851D9B02C7AD4EE8386169A244DA1E875934FD3DD93EEFC698B55D8D0057F0ACBF7ED747F29C2384895062C65E571D0E4088DFA1383A91698BF819DD88D5172EC1F5B5F8285F41DD8BCC7F0FB3F100804028140A07FFFA71786C6F4DB767F0B72E70B4E57C1A12FF7FF4ECBE1E38AE364AB73DDBCA5DEE277101D29FA055FCB3C9371D549DC821B9284C25BDDA3B77DEF1F59244EBD1E021AEF694E5C9910DBE60E8D32C908BD280C1002BDB082CE7E4FBE9CE5DAF951B5FEB094F2F7C9CCC214241033E0D7D5D1900991A0F7ABD2B064D09DDC97D5C57F75DD5037795C80065FBDA42711CF56F4689A2E7EDCF9902C9050AEDF1E995FD5675CA0A0FDFF232FCFE09FD61FDB6BC7A491E34BA9B57F102349D4F267A3ABAB1659ED74E4778A3D6C847BBDCB7C8771972F0AFA8B52121D554DD9D5F433FF52DD39F5C9D7E5DD37C9BE5E3B38C759BB7A99FCF9FBB6775996B5782C8508A1ADE6BCF687911F0A07284460128005F1494A6A08EFD5CBFB6BD506F0339614E2CAE5FB2D18D7CA2868E779D91577989CFA195C95C9CD87F82A27C5352F67FF9852B1A4FEF75C4ED969FCDA315229A7966CF77E91E9892BFA5C18FE058FF52DB6A0B1DE461597BECACBC7744AD0C2ACCF8E7BA0BFE430C7F9DD3ECFA6A7AD7370DEF50849A336E4404C1DF6DE4CBBB4759FA5A188770E215D556389AD1CD4809884B07225ECB20B440165D1ED4C3EB5FF9F1114D9DBD1AF889468986A3B3EC97E0AC4E665E83116FF8605C0EA293772DB9E2865E267689BA984A8783510D83EEA6DCA323E9DF29537E6E90342690942A5EE12E4B81E0F36F599AA3E7CD65D6C70AA4FB3918C41C5B92A6231FBF8A6AA9DA695DF933FF6E9D7B371CFFC2FBFE883F2DC0FB15B6ED63457412EFF9397082AC85F8AD687BD0719014DCB2E706E77C9B924B3D8E14A34217ABF6A437EADC0BBB27C1EB0E919DB5599F5AF8962C7B20F33D5AD6E7E0168DFC069BB140ABE1DDAF63F197B0B5692D875FE210C578DD8501175F101BBB6D6537BC8FE2663AA91812298338AB5F7DA2B88768538931D8F66B5D79E667CEACDF25B5532F09036C4DC3C2D9D9615A83E840322DD7BF1F819A6BEA5365F7FA0626D3B95321E4834FD907946DE1F672D21C7BDEAC0F8092354B82103E1FB110E07FB18CBF7F605D11A8B0DD9C4E134C8170BB6E30F695AF6178E320D6CFCB70BEC982E97AC82E247DC633AE8B44B3CA0DED2A668ADF94F87A43E7B6D00FDB2A27234704A83C1A7980D254EC159521DFC8947242062B6865CFC14FD1EEC207E86F30BFDD032281710DE4F3BBD9A6C996E8EBF257D544B60923148CF2CE40CDD5FE330DC428A9AFCFA213282B3E52B92EEAC9C869E6BC2C2BF195F5DEEEF8D9693D4565572E8C7947DF28D31ACC290E9603A0ED59E94DB01732186F398474365ACB6E592156619F5B1768FF83BC5ECBBCED304249FE376123A3B9866707BDB3AD59BF53246A60F623E5432671F3FE7F9B0463F70B9B0F4257BFEC329FD8C53DD1D9D3F9EE80104919704F9897916748CBDDC7AAB709099CF6BC618691AAA9977F74748073FD83179CC1A64D41F8EDBA1236B3092756A9DDBAE722BFDCB33A0C609D1308109308C040574FD1AD352C553ECE2F3C36F28F2DDD32F7D40C29363CBF5BF9DDFDC4469A46CD82352065B63DD2E73E85A64CC2B9FEEA6F0ED3818C04A74DAAFA3E3CB3B6A2386946B6E22D1C997BEDD2CAFD9421C94758A18950DDBCD64444957D41542385B1FC0F54C14AC24A0C737FF1F4B834909D68387CA4E335818162F1C16B38310494788D15DC2B1479374281F60524298826D9A5E548E72458DDC214E37B5DC9BF72165982DFD5D83BD706681CF0EDD97328C1E8FA03CB0E5614F3289760383E365B14C0EF4D56AD6D4A7A33AB0F6FA6C383DAAE972F7EDDD4BB6AC58CB9FB68155328B0E8FD91BB4A1D732DBCE29AB2DA35792249ADA5F3F3965427DFFB63DC41126FA1206E39B9971185F9A6040A531263D6CC7F1D31FA5D4E4ED7D1277A0187649A55F50BDBBAE0A3A0A6838192CEDB5D63460ACDBBA0FC2089E317CEABD48198C62F376F8DBC9E1F88B5506E3938B5335DAD90A77DE87FB7AE7A8227A2974F89768D10F8E99889FA5641B9311112082A2ED82060A77B7E7964F35919134663A000BA65740A69C7FA709BF50F59B19FB75CBD6EDA9C8E2B1A1CC2FCB77D164A9FD79C81D61E2C2B8258CED608FC7116BC1D07F1C61A50A1EF8518069F1790DACF4122D5B1AC2AA4165AC8D010B3689FD842D06F80C350CE2A4855F9015FEC85F3F36F0526E202676E43FBCA290B38205375E7D037955CDCE1CF9B766C1F6197CC1595808956051CA07F52F8123408FB9B44C59FF998D1BD4AD802D4CBF1E453362BFE18B150CE45B46B06AA01AE40C5807EE304D6CCFB7C01095206E5488BCCE6E3401F07ECB801AE94D69C6CCD059E94083CA34591D45869242A87CE2D34C0092E972E56E110D849DB9C82E51A8581318E881D1E8E8F035DE39726C93B44168E1FBCA386D13F14C6FF0D95DC0C92F9A6D8DE24FE7A36980DF8235075A2D3CA89D3C6240B491BC2C49E7F1801916243D2478F409F700BE751E924EA68794026476BEF57EE00C328DFBDE89942E9C2FF7FFB415517B17B844CA0004E905030DAF9B7CC4ED3EFE4BC3EFFF5998C956E4AB1371CE4C8F128C5207B0531CAB2903509CEA78281E64B4BBCA5B7368B0684FD7F51F228B4DE0EF727150C360B9404A8708177328B78B0645BD230206DA7EFD82C12CFE261DFDBAE2F7FE19B5F6208C74249C53E6B77CA93E626E5BC71D2FCEA57317B1EDD6E963546BC820EFD4499D2022ACE4446E2DD6B4281086FD5043C27A57D99FE7278BEF4C48E8B0C4211CAB232461EBE1581C77183D3899CE2CA1B3E71AD39CD3FCD38F0450448ACC0C29ACABCB6BF69BE458F1D11A73FD11F62B952E7703B15950FF985898DCE697499C4666C800F259467BC989A155E79DBC56968794BDA538459BC157C5C05A67A346023CAE6A97A115EA09F9E42A64EA7DB80FFC4409FDBA0835D87FF10D687B5BC3A8BB17C27467A65018B770C78B738EDE456CBB46FBE0293037190FD6D86919FD1D23293D3816C7CFE7A0CBDD60D5C17B6720868DC657EA99AECF42999726DEE4EB4A71A14053FC07E9F9514D70F5F0A18E45FD3766AF676B70AAD81BDA997773A4747C90DB02F2FFCAA23B0F3BF42BE3AF9AA1C743475CD7491C3D5C72C576692C97F9073C0BC9B2D007C7FC508AD0754F6289EF18B53BC1313A9F832E77433BCA7D85CEF00C4B31C28DEE8BF1FF4ACF42EAC3F53A8A5FAC0E8359C960E98C1D8D548714CBF566AAACBC72B563FD3D7C444162AED8AC117E150854F6B11C8C7E61217C871F3DFC43BE6295E985ED460C39C546B5C82103DC66B7911EB33EB8A4CA61627E835D35BE6324B603C7E87C0EBADC0D120737703E35BF846FF35846496E369BBB7D6B3A1C632E2A8BE4BB1A5C54CD6DD0CF15980451C7C4E2541D54C5F5F716A2081A34ED0B37DDD2336B38F19192ECE857C63EE6F4F892BCB555721CBEFBEE96E03FFD12CD77E0314F16F33E79D19EA6CB454D6327BE623402C7E87C0EBADC0DE7F71D072E9042E3C955B33F2A7FC42CD594DE8FEEFECE60DBABA7FEB879FB70C3EE3284C3B2287188F4993AA53AD50079879444DEFE6538202404576BB46A6F1BFDC26CBF3B70FFF82C6647E4F02E51902EF49DD2D87D1D32C023781BF929D807F73DA5BEC7151B6CC6778C44DFC0313A9F832E79DC43FEA9FABDF74B30EE63FC8318EEBEF013B776970AD5FCD445CAC81DD8C46A894D1941F3838CAB2C07352C675268E2571069A5EBD86F75D56FDE5AF32FF193E3E73280D945640100B78BA63380F03335D5B7FB0A0F0DA9D4C36836CFC4E255BD4726F5FC0D124F537EDCDBD9FC7F088BA4339F106FF77131916D681CD9DCBBD93D2C7DA79AF09062FFF5962147A1423218EED2CC5D428ADFEF671A8BA1E87AE154AF52F58E6AF84DA39D1001CD06F1C02D49E3DEF91BEA97DE0734DF0F10A27C891702BE7F0D749ABA96BD2C59966A65471035CC3F2A47373BBE7D18A43CF12D029A4747FFF3D67B6A11F24A945F09F940657877292471731CC194A8AC1B1C7D6CCED5C516F64E2C55B56E371C4C39B4AEB9FC544C6E7DB15CA8EC964D9D1735E205A7E5E5BE5B23E591885DA4F48104D0B9A6A899091CD3E6CB4A032E16EEF4D77778C671504C4EEC626EBC240C746F08B0E29B38B90C19D0BA7C1B7974F91F32E4703C7FABD28DFCF1DAF79150EE292EAA5DD8734F6B40DB7B8BEA58B92CEF056F9A5EFFC411A5DD6AD3A4B348B1C114AE6824FF64E1558E178BA2B6491607AB13BABCE1ED466EC06B0D8B4F99601286E795ED9A2F36A366727A71E63BB76E99AE71DE61A0BDBD8EE862CD47E70BA1501D1327F48D05E6DAB715FABE3CFE67DFF438653F92D962C53E60D0702F2963F964FE0D492CAC56303C89155FBC195425DFFD6D66F6D519A17556741B2AE6F17960E2797B2D1BF85BC8EA289A69D35E67AB8FB53817B8FD923B7D7F80AFBFECE22F067E912CACF87349F1F1D215540F416AEFF87DEEB2961B1D5C3F45EF4602C891E438B27F38D17F9445B94B9DA3698002AF7D3733ABDA2EB23ADABFA51001AF1AE6F4E3F903EE51548B6DD89FBCD779F3098EA85B17887B7DE0DD7B1ACAF779655CDED7E55E9232BC7FE2D2B75935BEF9A9DF5482B90B89D865BE38AC3826E473ADF0F75B11E153EC1D69C31B1BFF1055B3DED68AE351CAEF3DF13098CD258F120623D18F98E7775D49EE49EFB33ACC545974516C2E56279D8603335BC8679CAAE97B9C70E46BC1A15E12C6E9C7696BBF0E108824FB981063C9AEA7CC895101263ED181E1710D0F0286CF709B32281E3AA6C837A333B48FEFEF545832C6371B15516A63539687BF223ECBA979942438CD5D795B6FF809F6F180D10D3D4ADD91C8E731D0A981072AC31E2CB26B41E76A4A6F2B87CE66151159659D45730B2860580C4F9C8E430EADF23A47CFB81BC62797010A3C74639D69EBCD99A4E83FE1B8149DAD3E9B146B49760E152854453DB72498FC13BE10FB31E2BD85418A82F7A07B686CE56713637D29FAA43C65F3877F8ABCC8B1CE1EE4ED72A7F2ACA604F657E04B197B5EA86DEEF07DF2B591DA5DB6F1BC4F8C47F90AD2B89B93058E2CDDA2B01D1FC4B82AEBC7FACC5874D89976EBD4C7A137B44D5127BFDF53E013C3283D28FC98B1565F6019322444C16FF0711F62FAF7EC0A679520D61AC729908D7A7A215D4D8AD2E1E957A376E7290D767972DF7CA8B8A85FEFEBDCC312D390739EEE7EAE36F37EC5ED3ECE595F32F1A110236E3FC32EA264CC94FD9098DEB9EC3FD5B57BB340BD261C613972E5ECDD9F93C87F145678E9EEA3C5C7A89CDF11B8A799CA2FDFFCA9C47477C2166CCCB87D6D1DACF29D89422F377354531A5BD42A6850A639CF26E354E094B53AD7C0C868D8371EBE3058B2052BD6A4D9845DBE1AF16F44C94239F5AE96D198F18211F0E3C370EDF797F2AFF2D9883C2D986C8D333002F41179EBE4793BF8BCA746A2D638BBD62986EA27F480E6804A65518727BC25900B068E668CF71DB869E20E720FCC7C6FB13DA88C1A3D572D91590FB4C012AADACC0F2E55601392DF6C0796854B03F3780BD5E3F13F7E0DB60E6C23D4E2B07A3CC5EA3301F38F09D58BC869EC51A45A3AE7C6F9062933E8389E902252D61E12F5D382D26D2E92ECB5AF26B1B2865892C58C343A22B9C03E23ED97879E9EDEAC90FE12315FBF6ABFB8F1E860044B59AE7EBD4D1934DEFD23661C472671DD3B3507DB0032784E869ACB47BB896333F8CED18EFB15FE99CD265737CB39FC74D93AFD7AF8DE014C0000000070E12ECA1D36BCF0C95CBDD78B9E4BAFF4AC24AF8D01E6D9B29FC21B98D48BE7CEA63BA6C578DF3DCAA6E02F1D7BF39E390DB35070CC5288E969237ACAACD9B7E6B5FD849D78A1E76169F70A2C550FAD7F55EAD533FEFC9D9BC47E3A5FAA3CC24964517D669A29A3884DF74420241C046F0ED74361B5A8F345A1E832A33E18D2397C3ACCDE39B7F4B07F25871BF92AA814009782A1CAC19C7ED4B0F020F0A0F0B03BC80F3FDBEC35497F9D4A8093122098FC315C771D180557BE80D143E3C68892EAAF79D0AB697CC25586E598A3C977D7DBB69D1C0A2A0E9DFA915855EF963A976167FD542615294973FDF6FDEDAFFBD6E216A638B8A6E3C8743C5BB1C064BA3CD8E28F7605AB6AC72DDB7556DC64CCFE462341D099B9E3B6D79E0AD88B04ECF9910371CC96C750470270E0558DD14D4B297B8D09C1D1FEA2461D33B60F04D5C85BB4BBBC2D93D9E6017B475A60F9B25DE144942D8F59B683DBCD5DECCDBA6538DBDB3873F5CB648BFF3CFCF6139B4398C98F4BC4AE8CD8EFE155859D70DE7167CC1CC249F16748893101DEE79C835C6D082E078B03ED11424109594F5895272C8ADBE57F1882AA67875170D7916C1B063D8B138CBED2B5594BE29F8C72CE1BD5B5E6376B4CA281D96A39B7F12A7A3CD88D4E50610C95866CFD105152C2978D8A4AC276D3D0980FFBB54F19753115B6F004A36420281E41A5412605E5475B379E02B8B01C527979EBC7645EDF91EAA932B7D79F1BFB08C634DE290640D8FAA494F42BFFCCB193552A670A47C308E2F779034D39EDB31FC98B0B3ED0D85F87CD760FF63B6EF89E5DF7BAC7A3FDC0DF03F79967E0C1D3641BF1D2BB3ED28D71C740399E9A30488E119EC1797C27F713FBD2AD1E0D4B02428C5DE2FEF7C6EEDD124CCBAFA22EF3B12964DEA8CA8DD3F12063508D1C2BBA89B73682729782829F773686E7E7EBA423B1EBE7FBF547B65F9E236199632FAEAEAABF564BB0BF64FC1BBE50A66C3234D9913D79DAE886600E4E5D35B4EE7BEBCDFEBBB3FA49B985374D5B406928179D4B0E8F079B63FDFFDDB188E4F9319CE8B3644A1B9B9E31D15721A895FFDEBB82539F7EC636C0DBCF01316F86CFECEF8AD7719802160F854D17433FBC289495D49B33F094092B0353E31D6A876FE67239E17E0C255619BCE52ABED1DC34EC78D4F6E09624DED8B5C921678F17663F7F7C4146325E7A12196DA889E45CD3FF1F075A5D76A64935C08696CB2FD6341EC534169DB9B6CD939C7EE568CCB46D60A09C737E2ED878E6CCD5A803289A442C71AA7A71F260F045AD4737168E57FFDCEDFFF9A87CC0017EF94C31780369C17FE527EF0DF9FBCF9170748E91A2B6D61BEADE54DBD9AB3E9BF5CAC8E2A5881FB1DC99C7ED26AAC3FA7D2101E724E0476770F786ED9418EF2FEA4E340B2E3C5A9AF2F4DC4B6A38DAF5D568B91E90EE8528C0E81E5DAB35BE848C9FFBFEA4299772E0C47B3F045FFD8E72675970F06C899CED7F07D33BBAFFED51DD4C89A762BB948A161FE520AB707966EB46461E75890110A612128AF737DE970457BAEE1F7AB40D3A64B6F3BB77D8F79E6B45996FD9EA3D87058A3E784B45B9E46A8A0B5831F8AB589B12CB4D72D4EA439AAE1A0D7F93878B417FB7D2583ACF2A7607BE6D84DA8B01F586DF0ABEB68B3333201FD93DB6E30D5E512D7A6AE7D9A657B6A2E9A6DC24F8E6BF261C2A712BAEC6B742F1DAD2DDA8FB35B259A12BE0CDCAD02F320E55753A55720F6547CCD6FDD091885190E34FC76CF04B5D7E0D73E7395BDB57602562DFCF7C9BCCC244984B63A626DFF133715B908FC37C6D361ECDCCA9379C02036F9E78FDEA7664AB6702D3B9E3AA97331E482BB44F27A2340287DC45D82B9DE8947F1A892C4716BF97B2B7566EFCCFC68FFABF4B9D57E871AA71A26C8DD3B55E4C26F94F74837E750C5EF1FA3FF847770761795A3441EEEDE905AF11337D53E3538E78D929CB3EDC2B88FF5AA2BD5A17BF4303122E0690C340D437863EF2DF57D1D8CB2AF3C9FE4C7D2D2FAEED14EB08810BA67F6F9116BA8D83F47B91B08B6E61DB451F5E96B276EBE31FF203FC51C675D2517C122BB7344C6759DB6BCAD539E7D8E2679D55C101100EECD6111A1C7102F5E2D77892E6C2457CDE5EF5681FE6BF8D3A7E2569E2AFF123586AA1FA866A44A43E6A3C6692BE77BE1995F607E6FBDDEBE33C491951447118F6B0B3003DDD2CDC1691728971D8293C01660AD5E17E2902E92B97F0137C1A291272064D763969674DD92AA6D44A76343ED34377F9615CF963F7D752C13D2E848E12B9AFDE455230FE1ADB90EFE80036A7A9BE4B3F0AABEBC9EBF338F4DE73C27D8E7D25AF4883F64ECE35AF0A23EB29EF4F36EAE12EC0D6C127981A16B484B0AB608922613BC2E476D699E11B4B21E653B002F3420B7BEE0A14C514FAAE8D251FA6A7ED6A57FF4E41585C429D7FF49B0F0B6CA9B6A91F046762D6322AE1C4F693F9BC2F5E92FDF49B0E8382C386AAFE32FB4EBADF6AA8B16DCCDD80C277897ADA6D4AF67370489DC923B12A54E86713DFED3325F9CC055E7ACDFB22AE5A68C272877263FC2677DF8546FF0F65778360E99EADFEE2A2E12C7DAF3F67CED394579ADEAD5E298C7B5BABC012DFA7A293290FD52980267B686F7F8ACE900A47FADC2A8A8897EDAE38CF51A02618FDFFB4B6A66F0094F2EC655BA44899909000CC56AB6FBD3A39726A59F5AD2A65222182F8B44DA4BF5453FBACDDC687370B9860504F423E0E5CFC913DFE0400BEF35F218080AA98639BF02827272259B52E7D8718B45479DE21B6D17437E1DAE1B984F6E2C9BEB971E2A3E9D6AD90C1C78BBFE3456D48A260EA1743D587265711A4311D962BB7EE9466A5AA3BBA34275D596B1D9484826687295EAD61E9B2967EA2A5CD13EC941D278B736C6FD4F17249A978A4A0D00BB1A6441B44BD2AFCD9EBF17DD06A7D96B1AF735DFF49425D966360D6A527646FD8A039E2BB9101FBE705B21157FE0D74B92A1477DFEC8057EB4CC7AF5B224FA119905B955ECE931FC1CE1168ACA1CFB3FBABEFA5401458345392E3DC7FF4F97166AF8D097D437FCE44FBD95A94011B1CE057686CAD3DEC11BFD5B3587C2CDED669CEA008E9988F0BBFE139FBC943B78828A792255CDAD7389A8AE2BF8A0B21CFFDDE7CFA66CEA7B9E34FC58D17FF16C038DA7E150066C7EC197F5C16BF8D2D4A511D1E2C125FC112C7B17CC948D5C042239F5EC9331DF19995F7FF4DD5B86B42590A87307E7AB8CF0AB976E2A63F20EE8A111EDCAAFB1399D670B82C8A9C75BEFE3FFA0C44A80DF6320B1944D5A5A3B492D19DAD2EA333408165E8234EBBD47E1B2DC0CE400D314ED7C94F343912B57DDEBBFD66FA46AB7B0BEC7F96BF06A3974DAF64DDE4F9BA0D1C8D2E985265DF28FDF6E5B43375ED7B6BD1DD0EC41A94FBCEC2EDF73B126CB45A854ED9A32E42F87223CDA981BA4316F7FD91EE45C2CFB30728B0F9B7CCE3F7FCAEBD332F0969CBC25F2ECC0FDDDA3E7FA7EA3BCDF7906D2D914C8763222F322B7E12E7188E0D8D85FAFF5C68FBEE74C459D7B57F841A11636DBBFBBE87F5D6964383A889F446B89CD5538B222FB68B065DE0BD4883EEA19ACB077AC0AFA94256D6601CC9010F00E512F4894832CDC64EECFFB7CCD3B31050EAB30FE5F93B5A8E4F4B4D98D3F5E0B8DA4BC1D7633011CB7E849B41657B3C9115EC3501D3360C5D628002CF5FFBE1AE96338472E5405A0C5B4EF09F4709255F5F8E5AEF7AA81AF051DA6112965518567AF71CA8AA57917A1F950BEC118A560573D7BE9E7CD628F4E8C853618948B1DA8BD5CFBD841CC91205051F94197A3740D32C3F3BDD70501F59309293140793C7A9FF9CBA319FA7B2CC5AE0D3869D037F26D602A93765D40FB31E7756C05ABF59AEF888FD08292926A9AE7440395891782E71FDE6303C8EA6626F4AD83D7BA6F1A75DEF3B1EDCE951C74046E780BA9F5644F103BD1973ED8B7C2D1C9FB51C73DA87F8A92BA4C24CA031C929A6FC0CC66B31313EF26077DBF9F8B225599EA8F893DF2BB8CF621D66FF71E7B5D2D0CF793679ED3CB574EF8D18AC53F56829F575E6C81FCB87E4F38E508D2A5EB2BFFAD415CE2F9357CAA594762FE033F71D075587D8331C93AF3C719D33581468163B664600941904757899C153FD594D91AA681EDB3DF2EA09E5E3502ED12BB2A2EEF3F4587C2BF2E60A2C514DC1A706DE26FEA65E786C2BF92814F341365836374AB2BE28EB991471FD253AEA51B8AA9D29DD6779218E3CCE7F197AFDD5F31EBCC9E82C9A4820312B9362603B2DA12A187FDFBF64A224E27749A7361CD1BAFD4DAB0737161E19C512A15DF866B660E116B30EE2FC7636D7ACDBA052A4529E5624EA582B3BD5752461694D6A97F1A6F9D713D397DFFA4532D50C904E7D3C287D2BDCB68FF7CBC2ED6A7CFDEB0863CEC30E7F2AAE58D2896C4B91FF0E14EEFE37421B0AEE0F61F5C58E8C3B612D75968EDA9D9D9B9E6F516B947C13F2A33AEE7BA59B136B61A0D5656B726E45A579021BAC8C48DF1677BCD0155261E882F0052951DACCD401699619C13E1CE17245DE5A39940DFB50892805834A30D7D8E1E28E9326E63BBBA0744FBF7694533614FBC5DB7FCDD8EEFFD5A01FA52B50F93EF92F7CCA2AFF48E2B63413C8AC9C912EE2BDD7439B817FF268514F1E19CBD97A6D8C69F003CA0C82827FCEC45BEDA336A112E34EF3D47C99A5C119385692F45FCF2321ADFF785918A40F9F274F50662F47C98D6B25613F2A982BB0A4FD4DFDDBF67B392779A833785CDC0BE38109C85D3086DAF0F437F82125AA7C8E1C99DE5AD677F239F0AE0C19F9D2E3B7AF44F750552E7A9466A15D11CFDE892995B7C8F60B6C797658DC748E40AF5E041108A1F75C4C708B5CE8FA52CDA43AEE88EEA98D22A77ADC827295A2C2582D27C3B89C60C539B4E72FCEBC67E9BFDEC1F4CDFC75FEEBB175B3CB4FA67BFB9F414299DA9A40048A7992914DA8E139DB61A1570245AF35B72484B47FC94C3F96905FDFAC978F18AFC7E263C694773C3DCB6DAE54A658E77BA55DDFEAE4A37B23E3EC451DF5A8E7589177EA05E8166DE6D28796DD9E9E88A2E4FDDF6BEBDFF910611608E7CCC508CB98CDB36B7FBF77C649F63D933E7749EDFCEE5B535FAFEAAFB47B2AF8EF06127FBE1B02464526E7E56F56F0783C4433D925342E651AACF1A49059C17E5834BAB52D846E5A790F17EA912075446170AF9C3D5124B63C77749864B4A6F41294476049A8FB9D6C6F19E450527A07027F7FBE658C4DF0319CC51365321BA7C90139F2A017BBE2DBB292121E4DEAF6D7F09327575B2E9649DCBE1979E04E1E7ED0BA7A556A19F509B7392205B6AECEF2D171194EE5BD56B8CC61CBAA1B41554FC8A5025A66B5BA9AFBFC166E4FC8EC70A32F1F5D953CC6E26E8BB8ADAD93641207AB23555E2BB0DFAC5B56D6947CE75B496CFEF267BA2ADD849E53167D5D610D3948E0251902CA8BCABADD5FA4FE4264E954E50901F94B5FDC34B602DDD1EDFDFFD3B981B42F6988537D0E3DCBBEF0D172A4E225B599366DCFAE74E768C726D4F685AEAC181D15464847A01FECF932FE6B72DA19631982C373B2E0CBE19AAFEA324E1738BF3E68E5CEF97D563E17E4992199A915CA0FF67C9656A35654E08D3B4F9FEBE48320D40E8070E28DDEA332A414A8DF9CF9C8F0F5F0F5C23CE5B1EC1331F7242AD2D9C7F85FDEB9372F22D174DF378F2DE909E2C19070FC6158C629AA36BE9220585638F2DCEF438FF5563D92FAC667669B32C81F69EF44B198EC088736AAC0D801D7D313522CFC58464556E0D100E06A8F5DD98D0F0714ED4EE007C5BB2FFB3A2B202AFBDA7378894F4B06F1E800F680365B2185032E56DDA8A0D0BB754687A8BDF8602D0394BDC954A85131FA719B4616C0A9D575F6453327E625C04ECB8EA427FD9F4FEFD3EE2D4685F5A056C7D686764FB5B61CD5DEA96C7698770079585D698D66E114807A0144966101B18D2E4202BF85F52CE68ECEDA0564FB37DCD14C41C16F0C9FFD34FED52AE650E9B92057CCAD93383129C94A0DFB984EFC31D47859340536E032B8DF35BFCEF103377140E4E1263D1E56D23B1A957B12439994DAE5732A007518C5CD72C9E9F7F9167B1E5A14A9BB6F21183C7DD0F6CCE733DF4D276BDB6F890D74CFE8FE11D15B2C88FC9EEE9ACAEBC269124A109761B34D7FE1FC7ABF7AF129B3BD33EDF228B694A3291524F427BB31F9BEC667DE4C7479ED6E99B866A79152FA6E8AC31EE6FB1E0775FFC8FA9B027BC6EA2EF815A12FA71F6D0CF8DBC8A0666E8865AA1DAB3491C5B6CDF20F2896FD8ECFD95886354633702FB7E315A4A330DA3A2154D5E691398DDC3769D63BA7A7E576873C9D3101A885DC054FD2C02709C31F49D917AF40BE9F672D2ACE6C9148AD635FA7AFF244A7FEE6C2D2EBB8BF7260C2DF3BB1CADE5933778BC530A8F7A931792AC40E367C605DD89546A8BB866E2128F49E1337F03C31D05A7EC95EE5C368C04CC311B6C97B69E39376F7D4AF7E59E509A3F119DDCC59B4E63631F89B7F09B675344B8D25B4F1C76A2FA3131F65F84E9D0B5C2147E69CCEEAB656D580B5C531276AAD664FF5D99EBCF842EAE1FC8D87C401B5FDACF27DE1FC984B158B32101B3B9B768D1F181ADDFFDFAFB51470F608A0507A8CB6A0010883870088CB05E2A6384320E9E8E8488C411316A1335C205E8A339D214C02015084EEA24D1122E14D49C70D022887042C84A1E0283490868790141ADE47594156095A9080D094149046C5A7E228E920BD185F908A4F01F1541CA3804102805806C4C42001A8045702968223D12672E810920EA15340FA9243B1580820515BA52400290CA12520B4A42B016276DB441008C1124C62C21F15260BD3A9EE3C2606C728C0D22180AEF6491C8426014693C97A541C034FA7D1CBB1A7A2DAEB364F0240900A81240029EE4A30D59A2A0C51A874BCE736E6F3CC037481E625A878FAC71A864FDB060B2074019D41A7D199406A9AC79E10530282766E46104031368280433F3C7F5808833382A4C520691A284C032910068FA5FA710418C998BC58A52D5D86B0CFEB174EC51AC99F2BDBE86969056170541FD9A51576C45B022141080D61709464267B936440F4DD84C159C59B9F580C9A4FA54B0853F176BF6705C9C2109206E219C2903C0DC443E6B6164140BAC7EAF75B0742BB7284875F3700C1543A9E042062E87CE75D2E1B8C767C7FC1F83882B8C7E76D817C4900824183102480D5DF95400210778C41324D2C2E3A649A45BD0294CCA0E8C396595D48601A4C02107F6890D877D16E6076178819E2A7D25D20001278777D8254BA0B9D043049D16930B236AC13C3A48434F0F8AE220809F3455051197B91FB91855C48005360725C9B960430C56A7CE2F8A9C4D9C6EFBA02CD514BDEF734FEE89B48F1D71BE24810DB4CA70A47194813D53CE5970F1263A3B6FB2674F543C7E6906943CB997E5F0E5157AB6DA4CD8B41FA8D911FF93DBCFCB79F949CF615A1BB90002422994602984BAC2989E44A26012C9712E13248001BD295708A1E862F1C4D1802A8543C2405A1E9543C8461D0E8688A337424269C2A2494125FAE345C610A9E9E0CE2AF063B4A2CF11A87F48DE554D4CA9E7254D5646B8304D8FD626BD377311987FE960C307A2D0083895E8AC55A03CC1F224DA3F010E63F8FA6746E7E238D965E8F84C1518584E8ABBE5C5284E9578F6A45935657B337E21E7297F6F5FA2E19045D17908F2AB83BF75EC6F3436B78BD78D096DB6760E65EDBC2A7044900B3AE1B84C1912C2506A16F894D834E08400810440A14419711325F90EF0B127CE0FE904389947C0D31700C1AFEEA9DFC3896653E819152FF4E85DFB5AE32EE96333AEF2EAFDF6D255264D5B2BDB6B93380B2964800F38A6B01C300BDF8572DF0665A1AFAE8D0C0B0687474383A3A808C4E244786A389BEBE91E4A828C0F93B410298D55D0914080101349A330960618AAD33A4335CB0D8E0D0A2E5E1502A2D3FB9804E0258B4E829ABD4C3E0A862C4982CCCEA57CBD599357CA3C49757B7029FB4041C9CC9ADBBA652BDEAF3AC545871D3C37E53AE7D850EA13DCA1C2CB76E96974ABF512479CB240075926702858FAC635C18911442D6478791E3D0E17161E448746014EB08D291197838342C01F9AEAF4FB1EA20666771CA83674249112E10DEF8805867C796EBFA05F40261464011BA8B2B8146712601A874C6222F8D10E0D84301341D92A6F6A3E9482A58402301A87A370848752101A82D57020D92E62501A8176E145C1C3B2499028A2C2E4B0121104C75A1097D6E3C37060D24D0A87C3F3648C3D15C18101A64D021706B8B7CB02201ACC802C6BB01585D0958BA2B8140A1ADF37CB322DD2080EA0281200960657325400084A6A530F12FD6696DFF0D541E8C4715A60A9200569B65B98505D8802DF071B04ADA0D25F094151F84C443F29B8DC0104085003164321F4D4848D840638ADB3B6548002BCE958045889CF9013412C05AED6686887F3816A94D27E652CD1313D0277CB01D20952A49A709534800EB6737E82A4D98812540681A2F55701DD7FF464BC91A19F4B8D8160507C138A2B6250960BB08017AA97A0344E615104FA512792FBD1B23D4229636C9252AB4C5C831542A11B93C461A6952E956B1AA11518D62B51381896A29209EA86D0901EBFFA1AD65E820A40E2F91A9D50D024E43F392149FDCCAB7043E22F8C38DE23320EF17C04704B9DC283E33A43FC67C440076A3F8AC8ACB8FF11181F00F314122FBCE35D60E17B3251CDCD8A66F96237212DB3A6366AA330B18A5519820913DC2F265C3955921F7B19F296B103288FDC50887E9BFAC34FEF0B8F4021F11F8EC46592461DBC746DDDA1D11096C9A00FB0C3520ECF3592E1E3D6E7DE005C584502D8F9308394A53FAE115B31F5F431E63AF62877BF40BEA16E069B5E77C443015F4985628D4191324B21E58EA6C6715D55049C2BAE48B37112DAC77E0A5A90BC9288542D22CA53F9BB914721BAB707B3285F46195BF974CF49FC9FADAF42D133E22E82CA0140A398EDD4C949B44F4B1DB068E9F877A1076EFDD7B2DFDC5F54190618244D488851E766758212B9602814001A5E7D1790BD60F3D2EF011115396185EBD03850461D49FF98F513D8542FC2CC97E3F6E12F08225E307F988902A2C2B076FA8EF33151855204864D9A71B8C3815244844F15A92DE7B2009D1C028D7267CF5962B59075905E5F11111E6810FB368184B2261A1332202081DBB08D33491162C022B5AE5F2DD0B9820917966B40DA9974C12163E0C1A4FC9445430BF494493DE77A55B903EFB279F8FC8E46851595421127A2C8B24CC448BA6E1377F02F1C3A2872DC4117207D31FE1DE72796814264844FE1A2D87EA30A16866F08ADD9133880CA6ACC3A2A93759697CDE8959273E2253B61B6591C64354105A980E6EB9026CB71431EEF708B91D2B5166DCA37F6DFDEB9BCC4F778690FB2C96FFDE3711F201A87950289D4367C99160BA3341243F2E355CA6C1F4D4321EB71DEF81E9CD9188828125F1243817C793842ED13785BF82F34AD6651CA04803C3C0899F001B41ED2FDAE329A688EA0B540F039176936BD29F5C4CD3DBB062122832BE8ECC4C7DCC01207FA6E3B7DD23266396CC8CB28E689527477B7AD52308A5ACC03BDE103618FBD18747A282A803E9B4183EB2EEE0275049D411CE7F2C11167B9BDD7C8C36974906ED31BB627A9C077835DA3C7ED8E004C5B91F74596086616938983D0DE4D23C693790663FA177A23B819FDD04FCE263BE60BFE1CE60317B071319078E825C51A08E664849B6DF1ACD5F81F5E22CE5F3429E28507D71207A5B46B928C73233D0498B95019F5D917706A12FC0DE9616E60BADDE96D62522DACD6127CCB38A24084C3944742FEF89C43CA3CC352A88FCE1FC73400CF7362D4865B5A21F4A9799ACFD820C7920D637CFDB3ADEE5C2808F955F330A903FE3FCA35C443D7C257A487774A7731B7B4DD613C49F82BEE47CB3CD228BF493E6E03B0BD0F76C72B5F9401DD5E1FCCF6A3936478C8D0D1DF1B6955A2664126C43AEFD2BD02B7D6C338D33C4B865A67592AE11859C372C11954AB7898A5CCEDB62B88373662645CE4F528EED8D2412CB5C8CB77D3970A7B7DD664682BD30B6709AB7BDB7CB84361FFBC4350D0B6261452A655F25F674ACF605F28BB77DA74773EC8759195BC8F9D8AFE831DC1BBDCC856F91CC738677658CB96810E9BF2377BE34EDE24803073918CA87A2E37A647A19469A6E2E6E20E7592C12FA7D1CCBD6946A420F486D1C058E1DD19D0C1FBD51F0CB260BB25B9635B61D77302A6F60834FD4DE8E47EC1739A4DF32973816387FAF5DE8F67652BF4541E71243729C7DD8125B3239A573ACB9B4DF02E745C6F10B690A940D80734741F0ED4091E0D4300CC9C4CBF1749254598407E5B4C00821931C05E7BD18869C2E4083F2D918D9A00A0AB301B042A2C9BCDC66E0F2702E4BAAFAD12FB79506D788848C2A7DE072248024642D4A15687C69CC0A5C23E249B5544696FC8A924A54E10B69DB825852D6FCE02A4AA8D8842A1995342ADD8C1C2EAA6D0511E09A3F4CD7A1F4643CC9A18A36A330ED1FB824FFAFB41C56C32170BD584A16549C048822ACCDB2CD2BB339B64A281E6F310BCD02DB24A46B737544ADC2DB1F9C5A3C899E54C33E704F365430F2B99E066936936E5ACB42BD9812332DECD0C183D9D5D0841BC965D916412CBB92CDAD49B3A995424DC6166B21CB36D537D7E7B2882B862BED6C3F9154C38A8F06F73D094468AA12567CE04609702318F2413C89D8001A8F0C630E119AA603D924BB495FFB82BDE70FDC070C0C439DF124E6C07D7698A641D9E39561372FCBE0BE05C3D0BE5606C7817BDA02C0EE9204B89FD3755D2BA5328A3E0D0518A6F3D8E0311B551D5CB587E7916BEF6A9C1DCD8990CED608220BCD9995E91C2BACA9168454B65AE26D51DBD494590DE96A013DC89589C0B3223F2CAF9BA2454B1DED1CF75D3E4F87FD6941831A00184C4CDCC7C703CFAF0A8F017B8DC852654AE41ADB2FFDFBE0C83AEAE2F977FEDCD6A7BBCF951DD7F2FE93D31727CEBCF66767DBD69D9FFAEC69804CA5C527B8787258151B95BBA4534C9B1936F3946DC106B8E61B790CDE5ADC8A61E88C78922174EE96CFBB5755B7934318EB7C5EC4D2F60FAD8723CCE25070FA73952F9EFE592F9E23EDEB7AEAED6B9FDC5A94694C253EC45A550F13AFE4F3398846174D674D2EA5BD856055FBA5D39D57F35FCA68E7B269C2C3B7AB6B84192F8D0CC546ADD9B5C93EF983BF7EBC6B472D533927AC4BDCCAD993C1EF4A6448D5061AD48F8C217A6DC6E86BE895BC5FB07426C78A42736695C0AE4CD76757430BDB02F5225B23669A59BC8D6A465EBFD73776FC28F4547A26B741666C443FD9F251064DD798D1F9573E3F4C80021A8EA1A05AA95F4A06FF7A2D1F2FF2FC792386348AFCB16422A7FF8EF7D027470D9A069228804EA2B82E0F98E34BE09F9EFD9FDA66AE311088F2565072A415B94CA390AEC81DCE56B33ABF4A605FDA402387D5262FF4E0100D812B3F0D6581D676AF1CBBBA3E57971261359B865CFD2AB1DB42A390CE2AD3E4703D01D11CA51B6C16C5BF23F30CD6D12046DD1BAA9A0E815FDB8C722158142CBA65D681AA1F82D4B69450184469642570AE86F9D63E6031D05B2E6EAB6A0E08365ACDDFCD5F65904BBDDACD5F3E7B1552C7BCD1CE49EFBFBDDF5EFBEFD76FDC5EB1E6F2CCD36F877ACDFDF9E8D6050BE0CB3B2B1ED976CBA7A39B3398B7C4F285CC2067AACA95B64C43685998B92B4C645AA1EA1A6C28EAA5EAD37D0368C2AC6D8F1CADEAEC248A992A92240A716C5AE3EE170393C3D299CC370386DC756EEA82EBF75B26BDCAB58E59FBD4C7A3FBFFE6F7B61E7AE9CAC8D23BA44ACD424F44669E923EDD0FEDB18966101B855C7DBA76CA4F9A784DFC5BA15481A5276F42EF8A084F9CADBFED975EFAE2F55363DCAF11DB5F7A6CF57E65FD31393D7F8A98FAE295D7374DFD427FB7FB05AF694E864E7D84A8BC1C9D57E5A3AF3A426EA6CFC40563F2A2758294A4A46CA50C754E4DA3255899A322C809A9054CDCCC026814440EEAC5ACEDB6F9006B06A92AF41A9E51A1F7638D985DA20D14FA4F5850D549FC753F2C5F432A43EBD697C8E054BBB07F2450D1E65242B528405648B1909929C556094D99D58A6880A904BD49D342E19861F9DC8DAA95419D0F26B26134FEAD59E1BA68CBC9563B1AC7C85964D2305B297E6154517C51797C51AF81D3F2152D6E108A1AB35E52B676FFF0D495B72EDC317AC0C7FA0F4B5E3FB2EB7CF5C77554DBCD254AC78E012BA8D353EF4523E0ED61A9C74F8B816A17B3AD9493B12225AC1200CA8D1A8D18F3C895F05F6279E123874BBE761EEB499F9A3FE9F4A8DBDF7BBBBFF8B9BEED016FB73DB1ADE7AE4441E31B398B3BAA70C45649DC230D42F16BDC96B27ED28A3CFA8D56BEE3FF3BB89F1EEF81DF7C6EF0AF8FFF38DADDE7F8D28BF61FDFEAB125EE41F54B86A75475B1946E4D8F1BC228FD92171CD82AAA0C32A65F90B967165A49E9BC2B67690CE4DF03E3617816D61445C96F5EF293B4104F900F574250BA6F5DA3C16505A2274DB04693F9092A3FA17DD34A272742E9E1AD44BEC125CB4E947C5AFA6594777759B815404B8B98FF25C4B74D0B3C3169AB1957810FF3BE33571928136C71ED2A3FC9DFF44DFC04CD0264B3E8C76F0D6B0A53842ADBB1999175BE43E565DF67711EC7705857786947F2A3CFBEF97663F2A545374DDD58A1FFF29E29F4E01F37F7A948B28E279F78E4AE1E46E33D1D9FCAFF36687C87B6FBB51AE51E2AD289BCB1D016C50EE50DBC1094AB0AC564ADC40617AE698675CD6BD8758B6045A6D89E1F0C15E43396A17CB7D8DFC1469795C440F9BF62DD9D2A93467C8AC97902D7461A56AE5BCBC29AE615EB366EA6E6A6A0CA5B034DFD9E69264D5F6BA665C0F3A218C1DF3A5D71988E6299A150512B56236BB5851AA63EC9A762A2D375CCE765E69782F78E173392F9942CE68942C5EF225364CBD2A93863A34B2B19C3C48428C7C7C1FAF060EE4CEDC504ADBD4C070EBC62E34E5FA9BD1AEF206997EF05B6BA6067964597069981CA0D2236402B59BE51A8CC92CE6320E1CA4871BF0AFB696C56F01E2986CAC3A4A7365ACE51F4FB2101DBCB4490D4CFAFCC193B64082B7C58921DDBBC0C36B31979623AC5AC8B9F29B1D9C2838751EEECA973176D75DC95F8E512323B31DBBAF5705965C7D08D8DCA750B6E3834DE64EB5DEB5219C62D30C0B67E952E071CCA75AF129B39666E6780FDC77B82907FA3D76FAEAA02E289509A8545FE058A0DB9A7833C289A2AED2EB857DD7054046E0FD5B23F33B733E05EEA90A8FE1F0F1B6D6F48B7DFFE6E77FBBCFE6FCE9EDDDD356B5EF7F2372497732E191DEFFC04CF8BDDCC540C4AE13E9D184DEC714575B3C76DBA304DF6CCE665CBBE12645C6CA34535F8CC85BA12727AD3C0E41644F674AE7BABFFA2C8E9149E3CD0EF6072C759035A0702D864862A143CFF8A8D30EA264520B824DEDEBA1E4E069F728AF9AB3C2398941A0792197099D4D681EBF366C0BB4B243DAA3627026F1B04EFCA480B9C688262B0CB84A8CCAC81F7230701AB0ABF1631E936F0342A038129228DF97F0C4179FBDC3E822D3C53F842E5E5FD7E121203BE269134816F488E346634CB806FAC4921112F1C2F4BA02606DF7C7A6DE5D3B234A83A9C9120E08D4C15C8C57B89EFA61DB21046B04B0CF8C78BA48930420E7C7B6BC3F3C177DCB22D9A983002291134F03DA0017DCA444A7B13E683EFED728BB273E02618813804F0FD40F575847F099C69FA7BF1FAC7FBD9787F1875490F3D3E04BC340F5281BC2F63FCABA2ECD1012F628FF71B29FC37F3ECC835F1FE3D69F98FA5F6DFCBB3F38AE2FD2FA5E97FC7EDB78A571C1FB05616E84D3E8172DAB4A43010A81521509BE7F4801D3E4249B945109848739BA871DBB004814C3E9FD7E5456C296D860C04C362347057264FAA081C8E83F4C9AAD6029F6F746572D3CB0C04518606CD333B91A9D941D9F075ACE0AEC26B21041B5415C2FF7DB31568A0750144A54DB904E21448A900C147C32A1F82CF7FB4218A154686E03B2296BD67FA547474C99EB200C19FCC302FA9DA1908F5103F1F1BEA0A3A286ED62213AB464A852C84CAA35F5C28980FA1D8471BA01842E3209452B3619F0B032072160813A8E2F2234148A2C4BA5E7673049980380508ADA186C1866DC615100BB1FA262774B35D79B7D2FC7A88EBAA0768D6F99413F4F7C4C06B851EA37A01B190D2DC88C6F98E95ABBE8075260F2B097D66B468292F50E8571142BF1A3AD4B80BF66E84DE45B954A58513DAE25A46AA4627544D30925EE6E6981D51D90F079DF01B57874D19903EE2CDB6E680AAE78B397256FD6AD73659A3D4A1553BBCBC840ED340A86B20132CFB5381177215BEB261791BB2CA1A46275A6F1A0E85A7FDBC797A3184F7513D62CFAB80B142EB712EDAA07F043769F40E6FB9E11F4C0B89CEB994A26339B81E8E73AF2B00B5FA47B7CA2A4F888A340A6C2910564354AED30622DA925EC829C4D2362C1ED09E6A403B658B9A43950F9B4BE1B12464E1853CCD00D5C58D1592EA41E284305221C8E1E2EA2919AF9ED23AA86EE71CAFEC4DA098A66FDC5CFAE4841618B8F54D0EBAA21585EAAFA92191ACB294A3A369EC3725560B0A75134DB43CD45CD3A5E786B2C526AD1A2708C366839AA92E3FC1CF5D5E773651197D4A6B919694BD4184074902BC88C65A57113F9AEC4B55501650784AFC9E806A943C8208F190D9C87B6080AFD9138CD1357F37F45146122EA0077D3E444AB842ED6E9F0791EA059B51921019A840C49AE9600FF49591355E4BCBAAD11EA795844880C852D1509086D2867C0B80781541644646528A2D9A48F79FB224A5E510E225DC89C5AAD2E928D08266B5C14532496986ED8203882A38BDE2AD846DA12D28D9D2C35F6A943195F639307EAC8216FE3F6B5BB1ABAAAD8481C87F2244FE83C8FDA1A6E37BDD1B2C3AC126B244941521CAEA1A8B491797F4D88C4525951A2A82E85096EC3E61218A213A458368D78C0491573392AAF0A44B81165C3A5290890244B3BAA9D92B3D53904592CEA75D8B5E27CA498D3735646A08A26B33126E6F93F7142EC4470FA95DA995BF663FE090271BC8C486E3645E117DC2E02EFEB5B15CA7ED685551ABA4656D0C7061D14802E7E2B651E5976E03551105AE7B466AC7388B92058CDD10CBA53682819B66A85904D1DE2979055C60EA10990A08D1B3FE88E596156B49E0369A6F2CE0EDDDD82470B9CF8D6C2BB446DBF998D444491A0363B923269C0CAEFA32C3C4552AB7E2B997F2807BD764A389E5ED3B4A12B86F15E04E6724D991FA581FE042AC245B562BDD82498A1690B514F7F8C6EA52033097EA8A8498904E6C3EF8DCFC082BABBCA2D4746B1A3B1F11FF402B04A8B920EABD8D2425425CC90B4A1A82D8A52FFE43ECCD2F36CB4571E8D7C56C0EE27E11E27E88FD9AF9B1716271AAC50CC44788101FB110F41253BF18A634C46789109FB5D41505645C7CA5BB3457E3E279A934E053A3C44F731CB435DB04A754CD01BC37F8442B5B4F1834702F6DDD35419A866FB25F6CD4A2AA3606123522246A3C16D5A9152A2466BC3688F461EAC402221604B4905D2ACA693C61738AE0DCD95D2465205EC9A5659D270F649189D56B510B16A887241E14F5ECAAB543E35B34D42239AC084290B84392931ACAB6D376072106E213537D19F122551DDB6313BF0FD7D2A910E4458D29BD8B9AA6303FB594F96F4FD3E2550BD6CEF214B177BDD0F8EF3773DE749F71D7EBAF1FB9FBD9917BAD2F779B3DE6EFAFE65D57F2C51766B869EDCA658D632CDD7B5912F119AA11A62B3C8076B5DC53FCEC3DB72F0E4FDBB8E5F089DC5FBB59E621D79A37DFDAE88BDCFDECAE0BAF75DD5539B4CB93EDE34F0D5FF7161C1A74FB6328D778ADB9E9FF39974E475EBDFFF3A25343F844393697B0498EC10F0ECE2F1EFB7DFCB8AF46F56894FAB5CF5D162333C3FFBF53975EB2FF87A367845DC8BCE73EB0EE3A6B1D38A89E7D3DF9C2B5411ECA5D5DE201B46B7CDBABDD963EF3671D7A70F933545BBEE2D41DF91F1FFFE96C1B80185182CD1A835C72BE72C0D893E207382B55A1A64535B3E3773CB1C3D1997C1876C7EC87CF8F6E5FC6BB53413C770479609FC4B1CC7B71C1DCECA0DC59C6BDCE50944BC28088F5D85F7BDA45BC8E1BE3091A4CBF9831AF9A3DF800B0C966FBF9286454DDCE081B4999FEAB55CC8BCB4314F3ABFDBF343DFBC950C02731E9700E1932FCB7793EDF21383A8087EFBFF08E7E84285C50D423DDCF52795086141237EAEF5874189E0F3D0CAB0612F15190FA5196C76FEA73434203FBDBBD3F8C928A95E79AE4D0E1803DA07E82FA3C46D62674142F438F419BB4851327CF9A81B3844C3AD99FE77D58D3A1BF5186B8CA69923E7FCEC1A3C4E2B8CEE585F72D14D97B0470403F42480CF738699199CE6C3AD247C2C2325B346A68F1B57526D3E00A3F43FAE0B3F7CF99FC969FB268AE407F5A1E41E08494FBB6A29A7E6EF569FDD23ED4C2149C3FBF715DBD9D1100658682CE0CE38198E562BEB105590315BF26F16B184E42A5A6D90EDA81EA7711BFEF7F490C3C0F013DB9468DE12ABFFF512EAA0D95EF629A7398388DAF2425BEA85F3C654E45440AF16D727B16C18F8E436A7D640E4112590C4490C1B842C9D8ABAAFD25EF390BFABBF9AC7664DC01F079087C1753FAF993A68D66A747EACB0511E2FCE3D7C1B4CC3B26D30C0531D6465086741205FF90934EAA3FB5C049060EEB8BD0CBD80DD25C71CE968F0364E1148A3A91629FA7F3FAF78E8D5DBED352578001E15649CC05DFD308BB7FA9BAFBC7978255CD365239FAC7C80380EABC0A560B51001B42749C64490CD88B4FD5B8666CC6399C8D6789F6FA906C7EEA0E46422C32842A7D7E599C934C5974466ACE38F16F5AACD20E8D27FE6AFDF61D7194C065ABF6A22926E332E95FF70D4C04B033334E491C2B18F68BEFCF9D5D8E5639AFDF95A93DB91D37B6140A75BB24ACEAC3A90041412010083450BBF5A3CD500EA8F1BCE3B0FFCFFD71BA9F10C9EEC34E31CC7045D8A9896E1D00E709A3269972AA3C496350F9073C007BB19CEDA3CBD865C7A247FAD3565A4CEA7E17203A0FC2BF8DD9C65118E0F587E36EF8A4F6E80235C8B584F183FC671713783D03F3CF2B8B29FC6B390748800B53E7C713D2AF5F1640D4F81468E33927CC06541ABC64D9A8A0DC40A7BFC4A728814C06F7884C747B31670E8E51D8D9BE60D27FB112E042F6BC3197417D48CF1D0BD41EF5A028ACE173D2C01CF5F947C73C13BE0EE385D96723BF4742E515BBA80F86EF52D714DA34C0846A20222E5B6508272084011042C54085D73142F8B3C94272F15C9CA022CE3987602226411E30DD714305E1E091F303CA6DBC0BE5F49F954EC3530BAD889695E93F653732AF32D31EA7392BD9F57CF878C57ABA7FF8034D4A50A6EE0D37BDBD082FBC570FC47BDC6A3F231671B81E1F39C8017FB705794851A53695DC620EA70725F6F7E6D01F471EC56E524293B89DA5C74783CFFBF3E122747E96CDF1E4982EE07FCC21E50425827D1828B62BD17D81FDB25DAF83D2F428A5FEE379D7B9B948F8A1F789CC846FBEBE4BEA617F7ECB16960BC6FAB3E75C32D5155ED7FEA4E02F91485449735597DA706038931E70961F59602F2B0B97557C42AF7D4808C38F80FCBF1FCA1262A22AF09EB936C98A9D07370F6DC9365E7BCDA8689BEBF754C0FD94C1E0DBD4DB9F3B98CA1007108C727454880404B298D210DA1FD9F3A77CA7B56119654E0B6177A9471507B30056A12D6431E1CFC92BAD48200201EF59BCC7A089D9E4A2AD3AE7C090ABF7ED70647B688D810307D7037A27E6F0E7289AC972E1EEAF5B81E8FA72B258F8E6D3E6AFA195BB544BB8127F41D2ADF4817298EB5163261989D189199EC619A488F4DC936AE0A021A9B6941A4D1ADD014078DEA3915FFCA362EF8E33DC4A81477B77209D98693A56F00B3CD7E77954076DF09ED0C738E42448285E34806B27770BE5616894298263B52A096CC7FB22C6460F02E1C93D85C2280C18E345AC39E3F7CC58F5C47A497EA4FB6A1B061E55D90A89503A2BF73F9BBFAB076828BD5B6519BC68F6346915750288FB750594C7DE778DA31E53B4126028D00B998D151D42E0894CF4806CB6F8482D8F29E6391564E2E9D03BD1FBC049611BB3DD09042E25E74A5F80564DCF7D0071295F2F08EE7D94F32DCE01E3E76C6C719918B632DA32ADAA2976B30370078C9D84E0C2281868F5BF1863D84C4A5DAC0A4298438BB9CF72DCECCCC5537042225EE16CEF808B07221C72027B9BF0A031FADB4B3649167DCB6FEB731F75CE4E9ACF8B769BE1655A110F1138E811C27DD04EED9F339AB481303762DC3BD22B49D3BD041806052A6009ABED23FC83F58127684CA98E4CAF44C39357DF084A1A76E41852434973932A36D22BC6CA0594C80032A23891F37B7A50F6517EA2FC4239403944F98DF207E508E57899F064140C289337890AAC40247B2875921D800BBAFFF2A9343647A73ABE98F2C914D18F1C004EE92451A7743F17A5AD5527A9FE78C7ED8D25A7C79F76262E6A3B977FDF0906B7295326FA7805E571E0E85EF8D59C000394DE8AAA56AA8464C82645496892A80ED34FB6140C95CFE5E8ABD6B17E653636011C1626DA78EF37D20E279D8E3C2365E8671BB50FDA2C78C1A45602F3B7A9335ED80A22A983083F281A3C2B3E466CC876C408DE136EB9AA83276EE93128098DF90475B939A12E8F900C2809F21458A6173482C4AC9EA812DE2D5D103C16BEBA72C6E9A73798890CCD9A0BC1F7F4C96427C1A70F9A016F9971E5800136E9A88A1B3A2F4BCC67B8A1F7D4D82F135509C91B64160C97F06772F49FB38B01E37A4E3FC9868D65ADE66AE152C1EF2E795C6F2B3782A7832A43D4842C70489C7D685771CC1B789255540A762997F31A81FE63278B73E58C298E936AA62090CFBB68A0D84A11B62D30F720973AD1F2C54D82703596309BD5EFDAE65DBEDACAEB47CC64FECA68CA2B38563AE222FA7196D8843BC5D461586B19FBCF926C11F2A82069BD36044EB86E19CDEE06AA15C04AE8CA48648E63FD2A97AD0925FD295AFC4F005D20BD490D820F72217FE602C1E4181433FD92E921242D975E8A8C7933DF1E411D3ED074364CFD7190F0D63FC9602F05E969957E27F0472E2AD52859FB9B629024FF0CCDAB1ED6EBA965BB78E4D3C365FE0550A6BF9377B136C65875C40383852D85AB3F68EDF3B14C8D4A7FCD7713AE1C0E82779F800E8CFAB4191889A3A21C24772B00455F07F7420C0F9966255DA74440DB1E1125CF3F025AF1656F4AA170B2ABFE4E03C38BE5076244FB1EE89FD99423F8FEA410CE7F1B276359F8575836728FC6ADD17FB35CF1455663729C15081D32A0702FD21EB03026414C8C215FD055D4DBFC40A59B4E6EA64D7E2767D74FDC6DDE6817ED34C0B1C47164B0138466FEE6069D4FE9A3C052306212A8D7298478100830207A4822232741FB75DF089B50D8050BA5B0E1FD22448504AA1567B7205CC11801509CBA0A361A8ED45A41CF445C978E7C9E7D6CEC5BEEAC03963E181751B797A74107973B2C5CC60833AEB59C27BC27028166D948000124787053BE714EB8C9A8829F7259612C72175EEDFF73607BA2483F3CB12CC0CE9D3EC0AF721A2F43B7D10661E8905544504E8EB93D3FCA6E58303F45432585748009FB554258D5AE00F75669E21CDCA8ED89A3F535F9DA0DAF7C6829B0DD1CDC3A431C0F0262140C2088E749F005FD9D874B44704DCA2B47E5F94B8A53AC4F3654F3EE04861EA65901122B4AAE5A1DEE06365A2B1F82CD563A62F8E1D3B871CF9F72357EBF603DE184E201E03CEAF508CEDC4665369CBDA297C9656043279BAE58292C6C4C90CCDC3D1904673467F456DF3FA2EC267E0B571B28CEBFBB41516EEEEC26DF269F8447A26DE0BF49292100066AB3AFD51CB734CFAEA3BDE133FF17F6707D2D690F4502712C26120FB00F7F090294198A8C2E6ED3FB7F65F09497B9F82F2425AFC93133F86A3AC60AD2F473A39FCB8ABD8787D1E76B2E87FBBEDAA564BD7EDD32505A77F276D87373030BC785B28ED1A134A723380CAD1F2033AC74BE120FB4948FC47E73FFA71731A1F0BB6AD5C1CC8B69C1391EC7A56D69336949F6D9CA18A029BFFAEA46945D7A53AFA0D69EC80D667D9E2C3FC4E875599DE0CD483EF668EA030F81A020100834C642AB40A0D0B3E98A2258905804A60CF2BB0EAC393C99C1E0E7057AF02AC80129315934F8FE42239B2D878003D3572D3619B0B8CF481BAAD1795CCE5333DF70140B5B1760712A9DEC718F24342C51D9CA8A0B7B05504F5FEDF33D9DC2C9EFB905A2FF6DA4021D8E2213CDC856EA113074A1D3F289A463EE8E1A33F8BA58CC05327117548A794BE4BA1D5FAB0826A93015B9BEF7A38BFD961B5E99A9537311F61EF18AF46880B59DB84CC9AFECEB49C5456C29399EBF15305BE4DB963CD1D22B4B2829D6D3D087040EC37D2CE4CBC1197FB8B05A1ED0B8FF8E659E961131BDF2EBBFA144347853B2050AF5DC1A85D6551D4F7D4F1FE7FB7EAD538E7032A157F897AE6C70E24894E27689E316DE7C05C4280C30A39BF39538125124020D643FB43F8459AD4A945C4F9177E0B3E7C9213E099202D4585307CD1C2D6A9982F46454DCECD516EE656CBB351FEA0F82E67DB74D3268E13589AABE491D34479F0A50FE8CC93ADF13C7A60CFD31966175CECB261B78E94FFD8B1D20A43FF2E81DC37FBD877B1061124D6DB61FC3F6F34ABF8C5598C973E466B88CF47E0368FA6212A692FE6C336B87934BACAFCE607A5B68BF8483CFEFC6F6858BC6CAC8C909D5867B84AA4B6C3AEF53F481BF730D73A382E0E6EB43DA76DDFC0E211B2E709371B8CD6E4DC29699ED7D0858C7414FE08AE25AAE7930429121B7EE7CBB9C3A0387EBF7F3F32F2429597FDCC65D0CAA5582FF10A12A7919E996E16141F82599B1377DE93BFB80EB0ABCF8FA015FC1B0511F66FF59C35DFF50F83F6CA34C754FD16B1D77DFD21B2079AD71FCE8DBCA3CE49BA437E04F57EA1C7539D488D6DC38F818CF22CE1F667AD6284649C89B9C95BEC95B8C58AB26715B394037700F97B0D3D875156E8B9B4DB3C742D9C540BFC5DD7C06A145BC5F479B1F4D7A2BF2E192174B99BB9DFE49FC65A66CB37BCA1E20FC2F7FD815B5F69348A0F92D4B7F9D952FBCBCA628F4071A5B74C7DB244187DA0FE5DAD6A901286C4E3B5023F3926CC45E55B8C64F2C77E91F7A1CB1923147B2A6A888088B3FCCB0C2208DE60972630816E6634553D9906C9CB41B63A39075115DF17F5B331A9FDFF867817B5EBC0DF8282B490B5E2C13971EBF7DB7FCFFCF6A3C6E6BAFEF5C4D7EF6B3EAB951BC9E8D26D4F7D71223BD222079F8F54BB221F79F01BE3D03C37FAEA29872E4549DA37CCC2D896A7655D84E5FFAB0970B45A7A59E647475CFDC545EC8D17D405F9CE425D2EE4E38D58BF908B491E210BD7C69E18DF6A025EFBEFDB57259B6ADDDFA87C7DEB74155249E88B51B63B5513070CEFA47F3C30FEC929D09C754364ABA09FAC09E21652AEB0A9B5F692BB6ED696C807FBCBD538AC2DBF88788B3168B56CB9D85488FA20A2FCA19113C322E638A6FCD201008040281F5E1208F60ADE8EA4FD16044582C12EAC5680CB905426E185553B131BB9A36BEF9C9B022DD2CCF938A778B581602E76DE6E8E50C5C463DF3D47A71273E0DD22B72E4086864A30D1FDB4FE2F7098B45F0E41E613C1CF5F9EB99FE40468AE1CB372C3252E93725B0B3F8198A9ABBA8D2262A364ED493BECD51F95101E9272FDD53FFC6E1B01F2AF7F8AB79575C2D21D9F89AFC1C9415C85FCD97DFC683030CB3D92E0D83EFDCFE062E1BCB2A2F809098163FB7344BC5887D8A9D72076FEC9213BC02F7085EC0AB20198F68ED0FC2D4F26CD7770918E701E166AC16665888FC3642E34DC80AC1714484842FE76266EEC8D50E7973E9EDC71D34989831EE9822F0D3000E749A0FBA5C21536014E905194E5940CB101A7349F731292E618C2E3DE7CF31E25772C4D20061D9A7AC5140240F97FE71A69F429D67DC2C8EEDB5574BC45780115F381B642E198AD1763D4776E41F709047E4CD6A9DB76FF51EF06C151518FB5FB901E3BBEE11DC22F421DB01B6DDAEE5694594690A2C1AD336CB99B999617162FDC384E40609527CF20DD9D31944EDC7A26F9E2C2D31AE9F690E876EBBB8E59C97E786912A3EBC4BFA0C2997AD88E16710B345CDF3D1FEC938A57C514B0DDB71AE9C769A99471A0F7B0936183F23793F5647DD452FC8E48AAC7AEA1BEB70286B08AB8D501878F711566D1AF192B1F79463B757D270E3E50FD6500BD15455B6F3050544741F46B4DF6B1813844245661BDD93413CCAE9B608B36F711F239C052A3075C0A24AC6A7A3FE360E37EF79EB2A236B1EC0DCA9411905032EEC8F7FD06CDF68CDEAC864BF77A9D560EFE5B9357A9255D0BA4293DCF20CE40013047B34CD4F0B71E8D5364955F6E42BC376665E601191B7EBFECF9879EC7DE6F012468A0327E164242DA3FB7BE5FC71428968DCE45A2921C7FE8071AC2AA60B566C58441A2C165091E55309A57833A82ED32DBCF90A885118505D4750E9F4897864AA84A211BD4841E252F419BD886CF9852AF60C2D3C2A441E509B3B0BCF3C09755ADEDFAE52AB42962A0C4AC97F1FC88099AEAFA45C02902FF096721C2C09AFCB5DBDF6A2D48627A2E99CCA297C17D5884A298CE956A7BF2B78DCC342E62EADA6A91B2C4FB52AAD8CED162C902AC1281830AA1319BD611C589C107372E9F4E258B0D3E8E8F9E8F2E594E8659CFDF6EB3B32E083FE6BB05ACA660FB1B323E9F11B264D6281DF4D80410BD7BB7375264D48DD8DBB6EEB4B7557B330FD12EFDC65962BADB0B61D1317DAE844AEBE83ADD0C442968D0B66AAEB66BDF81EC02541C46C577FA6FA024A2FACD985C85E9AFC109C2B9B14D8408EC38E94E6E621EE652A72B347D89CA68EE4D3697A7FCCC6CDA586CFAFFAFB0EB49FAABF25D0A2B21997F4E6E98DA2FDA7905FF7BF37388EB643186315FC3DA91AB0576C57A2073802C3423EFEA93F0238C6E6F4AD5969F53B38F5F52AD36BB876A219488B66FDBFD5919BCF3934873CF7C18B961472559AD7E6DF6438EC1D8D33AAA10F4578DD5B6B10E2A56EB9686B05F367ACEB0A063070A5F950ABACBCB97CF3C7DF230E96A1E75A49ACE5BE6BFBBC4E284FFC7877AF0020CA42753EA19498965CC866D05A7AD92208A1CC2E37BE97180E6CD36B3737B2A3F1D5786A554F32A2DB6EAE0CFA8C463D823918FB1B7715026D46C69A4DD6A3B9BE31BE9C7A79A61362CA66BCA8C0048680C1DAE48758C12F6AAF9372D81F495A6FB9BAD00500CF3F5FB7309BBD18F438D806EADCA5CFF87FADF7F9132DFFF6D063325B9D03CE01787B5FAD9519C4081E697991539ADC62582CA2A9A4D0BD8F6D2993D20E9A79A56AAA701434F86181E5E66DD402E73778526BCEFCBE0439A918345F56D1FFE2AE604E1074DCE1ED135C0EB794EECE0ABE1DE524594244A48A911157EC9206D8F727D8BB572E89FDACB90582A126A7CDEDF9B50A8DCD4D6E4BF8CBBE2B3375D8E36D19FD4BCD536CF311B78C139B327D06E9706C330CF739F584443EF9609CF6F67B2FBF1829350CB7507E06AB9018C59D9D2BA645CB7341EF777A969E8F19EE0EA2FEDE3B2EA060032E7167918C06545A49485F5DCF4B1DE4FD5E6FB1C7FEE336A505751EF7722CC84769DF477DBEEC8357825760762F2170CBDB59D9B6C697314A3BA2D94EFBFD1BEA273C9350312E273EC1376C92CF27CC8D8F5231C37A2EC47C7397C9B23A3B00A386C358F083727C66B1D30A13C1A74CC6648CBD08E64C4721B20DAC78FEDF657374B4634626ECE119351A6E83C3E8DB32443F33D75E28736BF25C0E1AAB9DE5D210E7375CB67C6F3275E38EAA84D04ADE3C0A047149D5CEDA7C5E2F235FDD79B911710F928B402661292E9C1DC27E0D9E8DD79423728F3ECADAC59600613E401068A744BC7739CFABDB589B29081CC3881BE00E98F03DFB2314FDB84506A7ED03539C7059D049CECC30DE211E6EDA11E2B2B0B6FD400A94BA0A996AC1A656960146C22E6ED624D96EB6AA71CD6F6BBB738D100C4AB6312FA0E586D3D14FF67B6F19F450DC589849498C33A083901A50294D9BE7B1A3BBE8549DD6589403DA20541562BE1705453BC62085BC8F69250BC6934449DC05E849D8BC8C81831C3836FF7C4E29912B89D6459DED1FC7E53D4868AE269E8DAE170AC94497B0D39F9FB4250E36DCA7667B54DDEDB6019E13D575B163D5797863370151B3D001E1576E6D7A75A49283DC1937F2BC3F5500B23D1CB6DDF25DF5341609EE2F8703B7771BFFFE073DEA9B7E8B610D19E44381BE2F4D30DDA526FFA7134F164CA32AA2DFC94ED1F94C7BF67E1EEBC7931D9B46B380AEA20AFABC457AF3C03F57E3ACEB3F44F34CFEA1610427C92864FA457F0BBBE9B1277AD9205A45400E8138E0BFE75B764515B54CA7C306255231CEB02FA545D3C0D472D84BE85E02A275EC0AE0D4EED26781539AA5ABE6950D275CD4B6751A2B11C33240E68BC16F0EC2866D000306E0200F3DF62980761AAB720510C388A0A011BD170902B36D16E7EF606F69F5605B61AC81166DC1E31FF83452DBA95DC02818784CE0F1CFED0F2B124EB84D1DFC97ABAC3BF8428A7A69D1CFAB9A3BE36C5F2D0CD0A7E5C39C0E0D9F49BF377A60E2BE6AB0107DFA02F1366A4FF93D392A4BD71C0F028140B5679808053178F1E05BC10F2156821F4E70BF84D5B509EF596C41BB49191B5D13B4C74CBF3B39DEF54D6E9924A54BDF0DAF5FA3CFDEE53EAF7FBC21C747ADC73B1DBCB0900578390EFDF74F98315D2C7C4EA311912DC9241D153623A47AB184ACA227FB84EE0173D7C72B83109504063091C898B865C6506D4B13BDC416563CFF18A519CF5E48203654A0F27C1B777702F0208123BD0CF61CFC1D94650DD621DB41960ACA7DF0E872D0A732D1ED97E3A03EA4C098D56CEB67B4C2EB583CA90B4849A2F67615F03CADEA7F192FC3A54BC220E99835B9752C2E5619D0C8A6D73B1E7F76D70324DE4E4CF3D773C4552EF5931AD81C89A5629106ACC52F0859F12B00EDE9B2BF62DBDFF6587EECFF9954BABBE6E97C71E1EA24AF7652DAAD9D7A6368AEBB7CD63966C8D2EED5E8EED6F0F455852312710C8FD42563BBC5BBE3079C2CFD9CB895FCF1E8F2DE1A16CD68C95512E9055BD5B2CA45A8E2749DC147283F04EE0002E2CDCF385F6D114A618ECA33DFBFBE53B391559A814205DA10EF4FFEA8E99D939BE40DB4A62653497B430642A336A4117C3D6E15D84158C43C9A90D9ED5352B94C20C0003636E0A6C5FA915BE0636922AC253EC95E70AEEF5A7748ECD84B06DFC8156B06F04FE54DB5D24314396F3F1681455C38D94D79782E6687DAB0655ECD91D99F2D120FBF33E823FCB7E8EA4F8C15425B625ADD656E4DCFF22A4B2D7AE10D644BB032D1EA98120F0E9BCA056CC5FC31CDECB0FBD30DB28DA179E572B385EA2E815B1F43491797D9DB40441714D072548D70AC87060C5F490057DEE5E05810D86584DA54D19A045528105C442771234CCBD2D9E1B59219907689DC5C17D927DE6D09DB618E762EDA40B82ACDD02818089562B861313224C2C97C387E668DDA3FDD2E0C519075D28F12D40B2927185F03C8D49BE990D496FF36D3AC637B4330A7D95965E2D3F57F6F200E122BF971AE89F4A1A55E91C4F80CE309FECB4C210B4D7123C3280EE94494427AD5DF2B07AA8DCA12C1E91E5B22295C7F94BEE4E409F7CA0B2502774F874A8FAB429BAE938053F3C0AD9BF221212B64FB111FC095E8DD20338E3F59FC4999A11AAF4E17FAB0C85D897228CFAF442055411A3C05DF68AEBB4F244647E83D70DFAB9FA8FE5951EBCD34353390C311B9A2B64851A4371480B26496E76BBBE25978B3A79F6AED5C3209522CDCC316A318CDF08ECC9EE75F5B3D7A0D4049BD9877FCAA304F7FB20961FC3EB9AEDE74A82F2653FBE1C7446FCA9FA7A2AC1324E67ACD87DEB5C7E351F7F63A80BEAA77D98E1BED42455A459CB86244D686B6CEF5C44D2FA71FD1728B3ACF2A1929FBB55E83681D689921E91F2519BB4B986F59EBC234637720C78B27EAEF98BC5BE73FBCEE39068230E326002B8EB7C6BBE190646BBF4BD4EC569AFC5C52E5AE96C7F88A16A8C3E70F355434C42314F67E44C8B953C69EBDAC199C04244D8849B472C24192152A6DABCD57EF8F879CBC63614879F1919D2B8CEAF8023DD96EB5640767782F26D1C2DB15D1235612E0922A0CCE1504270E82DEA45ECD9C71F45B0241BBCCF64C966803A8987864128883FB4F11DFB1D1791EE083BF703106E4AF2107CD99992DC23E547CFADD1B65C8EDF1AED7163A33D5B9E8B18BFFA5ECDA5515C5CDCF2E073E9F96BBE69BFC8CE8A60372AAA9645DC76215EB3A8724CFDB1A012B890411BB3347C47F84DA477770F7E0475F9B1F718B62E8623D9D851FDB7C5E5DDB38624202C6B0BC671452382B229A748524CCE54013AE1A3C3C8CE5434C3D7BC3DFE6D242551E8B235399C968C527BCF4D946C1C4BA5E5292E452BAF52E4C60493F58F0A7E13AA564AB5B3A08C00085933AFC0D2A7FD375B52C41E69B5FF79BC113BCEC47295C5CC387631EC4A070C029AC3329F9383182CC7116674978997E8A2046D102A6F433BFE9AF98E833CAD3DDBC8AEED4D7986C7CFAD55CFEEE5001918AEF73764D0509E6F0DF087B8AE711A9EBA907A280CA129B932E1E3A1D683EF711CC78AF1626C2C9A9EDAEA7E4202D27C3AD2EE8ED2767A0A0E8EDC5EDEAE22D2D23ED2CCD2F20CF2BE4611B2CE06EEF6CCFCD6FC81BC469326BE0D168D9F90D862779AFDE18E7E707A36040E63E875D96FB27FE379E91CA65B5A5A0AFC55B35DED4E079E67CBCC922A43E66009BE88CC635F3B79A9CAAAE4A4FC32072EBF0254D4EE820199DC7B3D1AFEAFF6953D7951752DA0A073D14B40EBD3428838B7F7E3608D6F7AFFFD7533E1237286BF941856B2803D53EE71A0832C5CDDBBFB05F427AEB8910D2A7B16D94321CD41335ED461F9AA9F7DCBC6AEC43D8C0F180A5F18B8CEA006A460792CDF4A002B7AE003B5335A69F5AB3832A67B0682A7E50A73A1DE96FF1C81A0CDEE426C996994C60AEAA15010DD81E1BE93CBD8FCBC2B41B75F4D828E3630D2E95BD3CA3CFF23BE280633A4720084F1879DC0FA9862A04344470A530A05EF33BCDEEE6533B802DB21803D75FC382B72CF703C1C8EBCFDF57CE18CAEFA9D662F8CC07996D03F3EEEB5BE11E9AA82C6E1193610CC87AD584CBC13022A2B39ECF9878023317E7D4EF821A5D5A76514CFA22E70AAAD0DF4FB665EC65FC976308CA0EF9912937971D4605AABA1DA43038594099C63B04E777BF9461561A4D989C39B36C90C4419145ED6305C2A0D31F2F166C78951E19C7960402668B2BA21FEE45831666E00341C3B8A994DEDF08AA4494A23F0FFB4858EAF86DA4C67A770DC40FC695BE3913ED87F8DD79A2E9C4FFA153DA790E27C6293D4509D166610C34CD1DFBE6579BDC1BD9E1069876CFC247AD1868A818FC7F6C2CDD84F7D36A8A1FADFF86121D9442F7CB162776065750717DE13592E0C0CA6628981031ABDEA4F2B61DF15AAA8EFE4FC86AE5C7C6588AF9079FBFDFE535047152ADCD11757F5E5B01FC3D07B5AC9F39CC4B9254069BEA7BCE91BC7A379EE375241A126BA2FD6E9BF4A2A1E05E5F10DC8327383690ED862A1D712A0BD1DE7E8C0748D6BDF48F71ADD6872617E9EE8A6C1C9A4B18E91EDDD9733C2D1A85E41D614200815339BD3F29DA5F479B3F5B2B0B77815A78E67FE2DB57B98C74BF28F3AFA3CEF621CD82A02010080402818DE1208F60BDE8EA4FF6B05824D48BD1186254AADC119ACBABD808826919C13D48EB2C2839A2C90262BA12D45694DAE85A043E671BB18DB7FEB7C2725020A6D12813965AD0923DD689B34BD07C05C2280CA8EDB6F2CB5DB908785652A25E9D83145975137E3FC515938FBB4EA6429FC0512C1759E2F6873327B9DF2EDC6C6ABA46E6241C9B96E4389BF8AC719C6A5C2170875013725CA8EE53B24918BE1B9E951861972BC7AD40B19AAA1C9D7CDB134A53161C01E5DD28EF1FA3F1E46A2CE4E0C53FCB395E39B1FBDAED4F3040AA12F93B00357CC2A67843543C4B420C76B47CE06C4EC4C7588CC1C4A9EA9BC35D55E4F7C8AFCBD2D3632F3FFFC135AC18AF38A36D4C7F18E9ED271034462CCEF7E7BAF69FF0921CCD27F9EA1F6AA18471443C61B712F8BF0D01C2B8406B6CCBFCAFB503D87FBF519D29FBA1E6B75FDB0C94B4A0E607AF9747FFE471A1BE708F50CF68ED9B84EF6A1AD4A5DC89F649CAFC3244DCA3A25DDF9E2BAEE7D06EB825581F14AE9D26B57D003D210E5AC928540608A0EE3A50AF4D2334387F46503BB582CE61C2F918A97EAF4D58974A62823E10A5F24867A45B7EAD1196E883FA4B87DAC27C8736EE2D8209011F2453FC68048D3FCC49B85BF4EAFF862380100BFE9AB3ECBD5FD072FDE1014102EE3D60A3A0EBAF24D719EFC7283DB74320A402B93BE5F7F7B3FEF89D391064F3EAF0060672CDEC4B5806419D947F8583D0D3C37495CADF9FF08C963E83C07ADECBF93048978E435DDDFB6BD5552E23086D7007A71A06828E0B8FC181E0CC14E71940E04ACCA29B4410D8A7464910845420F73BAE07F5C7BE16F2D2093D7D62F8034262339BDF8E7C5F0B573FFD0682CAF270F75E3F5C2086AA34E258FD2AE0714EA96AC4812B6AC18793CFC520D841EDD24CEB80FF7F710D78B6F4A1B172BF2696050B2F387F8F25EF9DBB5A18463C8A226809FA4FFF3038D487D47BBF12097643C6CDEB408D5430C4033F0C0C3AE766623E810C07ED8A0B9E8A0AFAE9915DF8ABC651468FAA901D6E2D002BC0D7B8E4969649255F432E23AA4A707BB370BA7F96B08EE22765364FDD29FBC085AC6851BC421E1A668214B2E491492685B91DCCEA7DA6819D4E407EF465600F037E4C22E92708E90012D5752BC6639585AC41700EDE9607D223BB52E561F38BCC13EAA63020B0D9D2B9DA6F8F65AF7758F37879F9031E9FAFE3DD36B4D39125598230A95C12A75A835C990399A7D46BB52D98BCA0492B28F23E7F718BBADE44377F01E0FDDB2046F12D81000638499F6C0F8D19C74C26DE974A98E10648C67854AF631BBF24E21BE1213F0EF203085E74B5B84F618DEEDE0EB5D2B923A60DA9BE71840FCA9C490DF68AFFD4A579E0B54FB0166B9D420A63A8AC00590E13C38F9CF5EC1B1EC6F74EAEEE78169F64591FA793154DA3913EA05504B1968375B90B89BA21E986E2197B18CD062A15A7D7A30EF3E0C77AF89872B166D15BDA9860694306208821CACA82A5EA2F7C190F5748B1AE9DE971FCF97F91571752FEA1762A14DBE5CC4FF4BD7BF4416A143B6B687E03F5E0C16A3FB019F5A9070EE31A563D04F9997A4E11658FED541EDDE0E11D04B99EBDC95C62370B57928B683FA25214477C2CA7204C752E5E7B581B8A5E85A7F1B3E16897F9DF17C18B1B49A4B0620070AAA674DC9F71BF74F15E9B46284B1A6A5E46DC7E5819B53F8295ED20484DDFF5A19A06C5C40ED8FB2C2A5B69B71ED022C1BA45CBF52254A94DA959815E27959BA31D50A3172188E35365116D189E3CB8D5B484547FF629C4BF8CE0582DFC444490AA76AC7E2264504ECCED343234B746C3632C13A2C2BFE40BBC6DF9576ADB21BC041AB9038874B76721B41458050318484F3F1AFB69FDBACDE4A3AF3C9A47DC609EE237CDAC692B6F069F4C816C18F217908A21B84A3EC9B8E2609DEDFB1CFCC9E6551F128B7BFAD52EE17FCCE76B5BCA2D71E7815AA64D26186452B9F9B423915026920F9BF55DEE7DF2844A7FBFA24DBEFD30FD47D90C4D4634C988A7A47B44DAC72DAA5044E15F87654B4351164876378CCFD200DA2DBAD29F5A0173AEFE46CA7D86C117D4CCCE66A1576C2EB3485DE46461D658F626D15610FC4361F3C4DA669559462870C6AE4EB874F24868DD0B2DCA3D595BFBAFD27A487A293A3FB03C2C54AC49137F6E3AB05F5BBAE5A2E929A7CC0B07C596F2677678BD04BF92DECFBAD9F0A1597195ED4732BAB490CDAF2D9CCC7BA032BF76969039D7C12CFFAF8BFFCEA3F5C6B3694080DBA7FBC6B3DC7B519DC4B198B79B6EE506FF8CDCE99376B1D949C3699A57FDADB2D4C62F3387194F70379C12F364F3DA6CD646668C2DF9476497DF3720448C02621406F4C9F0974467C73C21103746B04C7C6062188E3684B31CDD6593FB36B8A9E46108D058FF916B7DFB8AD25A18E5CC51666207C04219B60D4EBF7722D2D17FB1F67C1EF8F131E31A92055B7E371363A5FD8FDBBD09503A4B8021923F532BA4C175F2B68DD599C850EB08C58620AE22C7738BF7E5FA1D57408D7B0E06778DCE9F9B56632986C77629FA16CCE2F7D9A71AD9C0A4CFE0C31299A457DA7AE6A36DBB415D0AEFCCCCAEA06B26B8913B0A3B41A89C87F29F9B0B73D00294410A2AC93561247A2DE3EEB2448D46FC2511B0CBBA0B4966FC3A1D7DA9203A78D682B732AB504150B80E19A68FEDC46FF0DC4C8182367847220FA8B49C698D7B2E2A9DB93E96F47585400342E00C058E3BFB401A9C4B5991093F7FD4094FF0CE6EECD9C76F5E6700CBBF2FEF81194974C8759241B4D56346A1B3CFC4E73A5B04799F88CC9F9852E7E19519249378F725AE6197EF4AA9ECA7C0D6BB4C2AFB71DA6B4F86026A7C1931C893AC96A957219F256D022628A4E81378FC533385A9634BD3A851F4F7B86C2A9DD472209A713B530C9EEDD0AECB2047266FE25B25891BED4CB61B3C80B0CF3FC070220875BDDE57755452080523D052757B95F26F3C16EA5ADD070D7FB8A7D5726B26F13303B0293F1E7B77633CB58B479BE3A7876CFBA2C187843C8169A4ACE69399FDFF51C8C17B8C953DF4C97BCADFD61E2D7FD0ED20E75CBAE25A93FC744B9AF69B0150E134CE14E32F848F5F0FB51278C8110A6E876BF50FE7E2CFFDCEAFBDD9D6740CFE6748B8F04124685B17CB0703FB5FA87FBC3A7ADA7C9921F85DF4B3CC9078D94A2884D3A7D372AE823C6F2F5242B60B09E07ABFF5E4434E39FFF0FE40B79D34644EA84745CCED05DEB1E58F5C87D6FE5A027C1BDFDA16DC6B063D79D19F1FAFB4211E6697696302AE5DD2F088EC8B5B8C26305C2863D61528A0F255D05C8F14854FF7B8FA173E038E1EF5E56380D6A6EBAF7F09E92E9AADA05F5DEE87E79795F268401953C66EE914FE13F68F094C4227900E4736CADDB1500AF07E3E2649AE0B3478150F5D0C936BFD21D354FB4FBCE0722655D3BFA6E5C12A13EE02488B572276486F6E95D15B552AFB1721DF81AB397AD1AE97F33EC34EC2EF5F4284FE58EF866793D3D6C5F4F3F4CA3288D3D3F677D7251021D34510FE744E01A876E288FFD4E97CBBF0F9AF671C49DDE733B28BCAC4CB4D94D7F17575219AC6F739528DC8E7E1589158238FF441D5658539BFC326DC0BB698FDC9ADE0363A650F0CDF3488E7FCC98BB583D634BED0C62F58D303242C44541E91251F899479CCAECFE09FD31A446DB8214A8A4A020E1C9D7C8889697C5D0A1CE421C182D70BC5D6D2EF513425370D217AAB14ABACC153BD6978DF777A5DFBAC6AE81BB7517B47610075A9718F1C724C41CFB94037835266B3A00E688AAF66F345746922984B494C1F30A1F67ABAFADA8185CF24AD65C2DE73F0934369A5AD5BD13430041D8151C779190402814020502A1CE42131BAFA530CB81611162B9D395B9AD2655C78B6F292AC08E177B17D10F2207FECA2B7A4102298463C486B1406A8C82C8FAF46E4F3E202B78F7D566415BD65938274869582DE343C5F7F4F493B033E7B2FDDEDC98CFA493E6D19A1483F70720F07613C9BAF7F4CFE949366E88BB8831695E996C513839A3BB5516F7E79D0068224C09B30212002489C9F204F8C82810E48AD7F59CE14A9AD3F0263D026CB989B9E83437263109BF4CDCC850A1D9E062063DB2D3E01CFEDB26CF60DF7B769D799357B07D1282ADE7E72F04DB021A2EE6F100804026D325AB4350DE5FBEF8AD8CF0E36CFDD4EAA263CA3F27B5B989AA0859C64225A499BE5308F537CA99EF2374ED703494377EE4FF94F5E6D0016732E36265CC93A6FE3D0543029618AF0561A6995BEF0F9F35968B38BECCC5583CB8D3D624479F2CA2DA4115E4BFE8F0A76FACECBE71EF78C935DAA86B8C53C7ACC8F2F6522CACE2D789A3BDFC8217F0B10FC9FF4B723432FA387394FA62915EB87B28CAF4ADB3DF0613DDE802F4B7CFD2AAB50DF4EEFFDFE290D79C47756E92BAFDC17D2C8537A6D0F6A89933E3C6B10140402814020502CDC4354B44945ACE5479A21D0F1E9041582248978C9D5FF71070A80F030BF688D65F5D99CF6B3F72DE9E7E131FC3B9A3AD9E38F3EA118089FC1A2FF578197FD1C14905171C1E89EC49104B8FCDE1967945F7CBAFB4DC219F8FBAFEDC1A25FAA4264A875F62093920DB367B31C7B9FFB472FCF7C217BB73E76C0D54B8CFA40C57D9207FA8F1FCA7AE43BF9545153C86D8A72E87B77A4ED0AFE199DFC73DD3009FAD8BEF408C8BD7231E1877BC6B9A0EFB1EE2FD7424D9264F42C91BC754CE361C56B06604309446C4A8A2FC6FBFA27A5E2679E8879BE19D3B6B249B8F75FBDB11644CF07E69187B554E455E8EBFBB8A2268CC98109BC70C9320A7731CA9A5A503669C06C25772B6F511705A5BBEDAF80AFA999A7BA520E781BEDF313520AAFA8D1CCF6FB7270A3876681E4888E36437ACEA9B893B3E1CA8AEA261BB2E55FA6F37FA2618817899D6C8A38021DEF1CD514B98832F4D104020C102592E9598452AFDE7F946D22952B19D8EBBDBA44FB97C31004FFBA79BB11B10EF8161B7BC8E89258638A4CD139618DA9AB727A4BAEFEFD19E3BD5F1D05176ECA4F3C92571B24B768A8E014DD3B0231822E7EB938DB8CE3A5C12DC8EC402DC233037D78716DEF57F6804870239F4A6122AF4CC70B4A0E69C5D5BF23261940C3B29620DBF7EC162AFF33F1E827FB8F5A44CE9D6554C2F9AB86E439C1857CCAAFABB226725C89B8FA6CCE934544CF0A66A16814BC3AD2DD9C94CE35906A19D0D829EC08E2890B145A8E16E79D88125D92B4E474D12F567CA519B149E0ABB28852FD5A831D9075C8662B718422C8EB3854BB9F25317BD3EF63CA958E4344CB776ECF26416B8236DC0F5AC72EB5B0B3B31F1504591659A76E5AB43B9F55EB55C6EC9917555D6BD9E17A9D8593407EDCE5A8347612BC5E0ECF3AAAFD34928DAB302576A6340028F8E9F28DA72B73300535655E9C65098A1F3564BBF58878988206383045A553969F4F333E8A6FD2877202E313EB6D7FEB2246382BD1C80E739F747B1CDB2D47695AD52DCF892DF6EBDB33F9C56A21CC3950AEB3A692EBBDAC56F9C16B779012140F19AFCE600BFB8637681477C25EB139E06EF7717EB8FF407BDDDBB45C5C6EE36ADCC6BA22B255F68955BA821FDAF98CA3E27BEF46AB36C2E2B2827E10EB3ED2AAC698EF6059C2EF2270D31DFBF675F4A9CFBFC98AE28A33955E55AA179C478A065EB5A995619F188BC85D3C188549F3EEFDB02A75041A6A9998F6899B2CFB37D4853A18D8B31D8AA4BCD717CBF558C32411481508A4808CC149E1FC7AD4FA612CCD729849A428A8B5A254187BF85217C507A34C0DF308405D219C921845EE9D3FEAEA9DE25B23D62A66081B5DD31670990F9BD2F956C44D4E7010DC23D80FEE6EF4C8901315A1231510495E95D3400B310EFD543DECD5C86BBE5F449494ED1CBEFA2E19A12EBD082FA2A47B9D04E4CF7E44F52E6CD035FD09F4D4AE9B546D4C0E319F46FC523E10F7866DC83891966F634094EB8D0177100087A539D9F654936AF691CF4B23CE297BCC16C9A92B9F1676A24B16E958C7F13438DA0C7B5878FB7B93138D17DD918BF8D9FDBC818930F8AFD60B5FD412B9CE7A0352B23A63EA2E684807E9F53BF330581D10BF17E86598F08D8267FC3535CA012DA0C9582F7F5A4C463C0CC50322EB5488BC59E96DF8AB3E70B3FA6E97B3E9FD1C99243FFA3D736255777A517B9CE7C222E2045568043CD7807EFEE00D0B041880593304443000E23C0F1DE85B8F540CBADB1A197257CB82509666A63A586117C0F68DEC707E3BD373715296BD0A327C678272CCEE6EEDA6C02BF8E2FAFD97D31E8EC7981B80E23C6241263746D2A4C754E11A7D71581611013AD5F22AF5FB147D8579DC0B8B8111E289A3B4CA868848447E9D0A28614554D60F4A5F657429040DE416C6CADA5A7AE909790E7933B938E039027E99D16F1397C5466D96FA0B085E03EAF231E26BBD6814A50E626E33BE1740CD7A444CA979F3F48DFC4AD777C0E7F0404728F77E5E5B22240B3DBE60AE9DB60FD29F6C5ADB10AEE8C48C8B17FA36FA62D2ED2BFFF27F231DDFEDA8640A97D7FA1050ABBA84C4E54FF2E18CE3210054C11BB1518CDDF72DC3CB8EBE5F788A34FD95873B3E41C8B942E419C8F4797770143EA73B554C9D1133391F3C7D9188A40BAC728BFD71FC096E23EC7C41224934EFDB3ACE8A28C11ABA4BF14622BA75B2FB98DAFC52114422DDDF517D032CD04F9ABE259CAEB9717C121F861C162DF234397996FD89FA6EDC14D2B3D77BD94200B0429CE22EC23F7B42361D2684CA18AF449EA84568C2460C9ED9EBD23C7709FF3AEEE0D49DA3A9BC30252A8B5FCBC83060CD9425A31B3D8F7C203241CBCB6ABC93A0D57AFB9FD4D9D869E37892F9BC3708903342317E7DB1F85EF0B86190E350FE14670AD22F93C0DFB889DB52E90E5CCDE943C0C9E0582BA0F2DEEF4CFDBE42ADE88ACE5575E9CF9D38447F524AF513F41BB7731A4EE7A98650C78FA4688019899BB06E40C8BA65605FB5F0ABF43B8854D4C84DEAFE0B429FDED8414ED8D6BF3FD4CFF5847AF6F40E66F6279B71272E7755557C3F6EE9DBA46AEE5B33525D3E3B9F84FBFE437829B07BE11A95284C91105A92B41E57AA3910F7F753B107DB1FEC589813829510B7003F97108FF0700F20763F8D09F894E430E077DDD37ACBCE45117A9BC141DC717BD67EF58F12AD2C1A8C5D4B12348F983F03C611EEDFB1FE849773B673F605899732D1AF2839701B7BA9F97A693BE9F8386A19E87B1B6B18CB7ACA5BEBAA9AB8F37BC9D869C91BFB29081B0AEAB93A497BE3BC12C2923A9862EEED45C593A9A855EB7271DC0D3D9B14922CBF61568DBA4387A69F9567B2073AB270BBF89E0D09855130106CFA52CDCEDDBEB46EB8D6A24B25D99EB18E01CBD0174D6CDB866F75CAF53805244794DF2207A30E7CB1B175829D7586882C2C2E965E0C921CD59DDCA9BDF6EAE3CD75CA421D046706AB919BF6721164BE8F4EFD7A2A87B6FF909438032525562020ED5F8826345CF0A1A669D5B871FE74EA73222023CE735C8E00ED4FF9C515534D14D68A3A9A72457708E610F3A109D6540F5B7A39C144708F603C84D3F1DE041A76C9412AC5B39B5CFFE8F06A9C46C023822C72780204E527E6DAC673DBAF6482A61435C5044A91253EA53BD45CEC9CB6FBC93A48FE6CE68325A60916BBB2FE794CBCFDD6C388A2B9810C30441AD124D879FC3AED50CA4DBA3B6927A989C2A8F2FA7D4785B86BBFEF3F2F39805D99FCA08A52D8D829E8632AF987A561C26EAB15033E0945B0A3F32BD2862EA9A1AB6C9916E35D080FF8139B4113F61A4F3E8527FEC1EF01068A2B1D1EA2D3D55CB4FC67DBB56AFF583AF465150DC8FFD07CCDC351F4BC051C09AAAD97C5FDFE65B057B76D4565FEE8A908C06B92F868B48087F852604974C5CE79AF4CBBFC7CBC8285197AA354919C3A148C789F7DEA30166EE3F60FA787E2ED5FE407ABFC8ECDE1308E3263F75CDCE3F8DB3682AADFE5B48BE986B0445BCFE4689A893DA80B30B5C3F08EC8811B4C33D40B744A19D7D65A5A3F8FCDB20C7DBDA590112C3DCBF590D7ACF50D600ABBD687932CB5E032888EFC6C16440F625EADD42542FACB56459BCC3A81816F51E8D4FB821C8F28C4287A64A5F9B2B81292971FE4627C00FE026A3E945FE6B963B4714B155256013B6649FDF30A4C68D47F543554D44A83D041437450FF434723A116F678A24943DE73ED39FD8C0962161AAB58A89B12AEBFCEC7A2D1B3902A5038591CE53C50F468C02475BDC6406B1C1E3E013B7E3E1B073B3B614121413E3E7B6B217E7E1B2E5B3E1B611E7B07214110A09EB3D1BD8F0EC9A55BA140DCC93F6B74C7456E407E8409530F85E11B14E433C07ACB660152C98475A42061C41A8501C1DCD2354D379F0E227BED0C663FFB1B1A60F5EE424FD7BD49D4A99B62784DA401A46F77E9EEEA168D7355EA4FFFAB242B167F2C925E7CD8BA828B4022D0307ECAE56BBFC2411E9637C2EE10E307F30AE65E7CF3FEC9BAA0809D425D849A0E75212F8AE8302673842C2739BB08E95F74288C82015DBEBE0D6AB1F1D39657FE35CB98D8F78AA91A0A3312A5BBACA31FEEBB281B1A80DC1F2F432E37E44FA7F0AB92DDA9E6B7EB59FF1F43AA04123937EFD6AADD59F2B8E58E2DF92C9DF9077E5B93C8D039FFC5C455059714EABC9C2FA29BE6E5F76FF57C78FC3586E839FE0C0B02F7656F124051304507F3B8CA38EE89E2F6DFB6E6D5CDD4B47F7816E380711858D85018892786C895313671436439F0A0A118D18D9352381894ED9C2ED3527DDC70C895A0CD8180F46CB75FEEAB31B61901F4DFAC0F1FBE17F56F03943286E57AADE194F0D64AD4E500EFB99BD889F7E1CE0CE89BE7A75CD2233F64C0FE39B101D3F569FEBDD339F7073A783D1DBCA656A744D991D4DC0EB37584C2FAE00E3BA81728EB31509E124EAEF48846A451A7A3E567489D11B1C438A4F5B363BF3839C65B0A28A38926151122557DAE273ED80D9913520B8E76EE58245B3E14CCCB1C5045A856F7CB5BA6E5CBFC0F346F69AEBEF8F95ECFF60F9180BA620AA8637609B9A852EA6A2958E7A354768AEE6D82F9531C225A02BA143FA34BDF545174BA820555A1A809603A53C04AEA4E8D202846C1C0E69DB9B69FAD63CD9996A0DE7C60CB9381E83DEC57B9D287138CC3548628EE1080362C395D23F1FA3298616607B1BE8CE55EEA8A94FA05B5FFF805DD46C346D3022E31C495000B26BDCE372F198501914A14398E2BC8852EFC24C241D5C1F00565FFD0167EF11B82ED43F0431A45D000FFB0B63C4B2CB05D0C610DE115D4DDE9F6CF97C22D0D3B741EBFE0B7FF3F4662FAC02B2028080402653A724364240FF7372FC1100FE4A9132D589B304CB0C38C75077AFDA2325D4DC4C10EB1EFCE03635B0624901640C2D181DD9742BA6912EDC8DA7968FFBF732F355FFB9B1749F2D372EB48625FD8C06B02012D8507C87A66258F1DE96A8EA65B1C982EE5DAE986AE2C1D417F5FBF3932FB98212907C5CCB3FB566378AC7FA93DC3F7C4738712A5725FF40C02217E9B429C1D4C09DA6630CC0EC5EF5276A9A8AF6C93459A9D7EE23AA4BB7CF9F570272C5ABF350E73B3FB8E27E7AC9AE2D53CF6A6F344574560100571747C92A6D18A24A2EDEEF1454A96F29DC9915384D700CCEBAD8C148D5D7CEF7861584A559A168C68E148491E049C5F13FBDA100491FB102487510CCF63E25CB2BC73D9A204BB3953CDF72BFE848492F3A172F25B1C8E2685A6BF464811245CAEF9D0F8D711B7C56DC4D95EC63AE6AF57C7857B8DDE8334A1C81140B6108AA835FB755B0781AED332BEEE4D6359FAC524164E1B81CAA77A8735650547DD9BE9E34E35EBD0E75C954EEA5D9D0E6C76881C2B1CFADA0FDFE356DBAE047802FF627BCA243A69C2FC9CF13E401FB73F3F53187A8725B99972557A69D62E235C7CA58A941499F3F1EA1ED0B90BBE7DAEBD315AC94C6373069EA07914BA319847048D26A9C11FFB6BCD80188501EFDDA86DFA1D294C40DE049337017DE19222BC4A945676DA31EACCE58F15868F00A3CD99ACFBDB0751011DDCA5D96B5ED0DCCE8A1B8EB0B36A47372B9AA818885959D0DCE086DC1937CF3C62D61CBA7FD04EBA6A057750A45F7861A566E3F7D1127214DA47D202F62C8C21D0CED84DCA09F42034C0F082F16A6BFD518C22E1C362323B1494D17CA31A707F867C639B06F3EF98504048F26E9E1E769E8EF599740842E40B6BC5BBBFF01F4AD8386BF1707B9AF8FB99F83B06A8F8CA3B6AF10AA8C919050418C84A3BB9D887E83808A8698568F807FABA0632FBA7D9759739E795CB4CEC524773F75CE743675E9D464E3FD54C022F412E9F319600826CEE76ACAD6B23E3D5D3D660BDB25C49220E16244A638BFE1AC1080681F6E6D6571CD22F141A057C43CDF5308D06AE65A178404B78CDE6E408F2BECAFDADADF05BE7495DD44FD4B83835B2A2F37D93FC962D3C8074D75DE1F31091FEA74F52D48C22DF79AE851005051236DCADF3F0F92F27990CC967B1D0026C95BCE4B037B00CD11FA7BC37FED367D75F75C8482140FD2D09FF1BDF8C991FDCB1391FBC47216B1C211026A8B3EEA3B09766D0F99B40117B5E7EE406DDFEE5E5786D2E63DF282069205FBC2C4EA340F6014758484786A4BF16DC1D40D6E00BDFEC1DE0F7C3FBA2A4BAC064667392B79E3E23D589A68E180F5816A98C0163DBC3F5DF82AAD04693C841A867EB256FD2DAB08C18FB2CEF6601783677A0453483A243E0A280FA6E21BF54CC91C6A905F655A146D9264822373B7C1E083BE11B2B1712E05B5512186023968ABF50EACA096716FC94D3291F6569DB657BED396B20F915DB29069B641FD09315736901DC67ADE89D45C368A36B6D945E1D2AC985068AFBC63BAF04F795FA50643D23579A668781979E567156B97DCB1B1E97FD0CFE785FE68FA898EEBA92C63FA518D656288C8201A9E3EA48BE798A0ED890079FCA11FAF32A721F7F2191446B115965934DF6832B00FF67455F5CAE6F011D35749EE876EE6F89BAADEA2AE7065A6C24F9354A966B79FF73B4C13D3447A5DDA1F50ABA314B7B16CB99F32F568D06BD5A54A37C8DE25742930630495BF033572652F6C6E5A92D616DBF7279E9A5328407C526122A1928BA77E35FB6CF1D8CF459A63F03DDBD0036CD65B6FCF4F2CA48BAAFCE2496819C948BA871D26909E56810E6FF963275AF6ABFE8495C743967D342FB6FC59F71BF2190B33421D6C1390897EC6B7B0BFDF875CB75E9178A40F2C1C3A03D27B7AB7A53F6020BA881A14BA3DB8968E27B9FB49C481B7F007C57AC19951CAF049930BD89BCDCA29402DB3CC5A572D5BF96AAA0B4F39E2394A17ED31EDCFF81407E2FACF991BF02FA37E7D0BBB968BB75F775544CA3E2183DEE83AFA757F1BD26E23140385DFAA4A547B1BDBD349484B2A01A4DB8D8DB671D9C114130364CE47C1916418D9B7BAD822AAD759267E07ED213578D8D1E95BE935F4FFE1A7EDA34B82F1FA21638DC5EB44F4922FD6BB64AF4033036B4A5FDFCA0C6853BFE42FCF13756EEAEFF249C64C3198C9137B2442E3D2C075E5F17D3EAAEB53C4E73341ACC505979A09BF0082FC92A2CFA298F7B94DB6DD1E9BE0111DA545FF38C1947AE6C39B49B1DE163CA954449443BFE3938DF2150917F9026FBAA71B676081D35C8C1D454C7397D5A37CABAED4BAFAC1B1450CC0F58A3C1E2680E9BC35E577001310A06485A6D58E3DFEB855819467374CB3A036FA992CE58A3B259B12C288F0951034900705044688639F32987E1B28E06973AB9AE9C6890845847626283A60DCC96F10DDE2B6BC51125A1BCD766EE491814352EAC783375C60C85126C434CF404A2F284D2F5BA68981444C9C16FEF134F61D57FF3C18BDB6DB10C0DB048E66AF84B02DA4FFBDCFF37F357E0AD78E383380FFA4B546DFCDB7ADB5FFCD53E283C080A028140A0DA65025CC0B7D5DE9167C53B4ADF5B41D164EF27CE9D54B49A4693F24D566C599A9F9BED6FAF927F37EB7B3FC7DF018EC7B31CECB3625371EB0FFB28E5B944F0168FDA5F444DA177408ECE27FFB274F89539994888DB12D6C4D14AEF4508A75B20A2821C0596BB669AB08DF9B791E9AE27D7F58F125DF156E25D8D0C60D07CB6B0183F4A085823E85E7AF37794634E7DD4C92B2B90BCD1C6FB96E61302DF1443A2C602FA0801C2291F8B8F0C87E5643E30BB7C6C84ACE19C843ED25405C71211B374C83B01347D5F4B703BDBFD4EDAEA688A7FEBB29950E55CC78D468591AFDE7084A0818F70542B661C36A13262EE66AB8FFF7B1429A0EFC7AF7FDF8553FEDBFC2E6C2CFF960BEED964A0F6D9B11AD111DB9FE94C22CB66508B731E89C1F7F9F233898B3A0CB16276B1B830C4DADF6DB98A5A6C942DE69B49138652F30D52900E8E934A175F955E2926DF3C1B29CB84E5FDB729FEB11164A034167FAE319C80D20BA9DF1B971152370D8D7FA7FF22F100520D519F044EFDD938B2D9ED376B331F3872DA431D51115D67FB67E4FB891670FB20147743F217A3A9BB1595228775FDC7DB15734809F7982F96A14875B58C8C32441FB3326E9417FEB4306A8284D8E03E7C9DF8BB11A5DF0DD1BB8269490D71997A0EC042C63959352A915A85EF5207CFEBA872DA6E69BF6E22FBD7675A29EBD44B495C02A5644B421A56EA2BEEF19912DFA61AD84734002D1C6D53C6CDDD77812C052BBD859293039C6C2C083DF6EE921A4D35E881376DE73168BEE68A513020F0887DD7699B2824E983915D732127B891D7B15F67BA2FD3DDA17D74A4DC6F0078F633DD3AEF71FE059879272BB093EDD0C62A0910AF2A7C926E16BA38FD24BBDB8007E3FEB2AD59FAC8C4C863BFD7322BC2467D51580548639F7EF1BFA9682397B4704855FA50A684FAEBF546340222A2E6D24C24D3190D687A8F65D7F11169D3BB940D26F6C527B217FD19BAAD4BC251B36B1D660DB20DA25C16F7F9AE6899203D7331DADB5C9A25DCD2635DE6771629F25F66FAD6C5A11239476761E1627E3B40057900EF43CB4F47AE0A1E23DE9E291194B1D50023BFB8988AE095A83045A8581FB26661786E07210EE3A4B5C8FCB59C27489BAFB250FF45DC68545D8BEEFB39C1AEA86DA22FFC388A7FA8F2312442548AA8F9D3B55BAB8034FDFF04756A82068BF10458AB2B20DBD3ABCD5A4CB45E8167A59CA71AC1E58B12CD38A5534CAFF4C5117FA813571C5B5A51ADBCCDE2614A3D1E092228EDE2DCFE49AA1437B6C44AC731341F08F140D15A65C73B3ABDAB30A8353F5F5C88E7B6F6C97B144660F225C4FECB1BFF0814B0F6EC22ECCD9AC6B446ACFC8C9B169A2EC0C7FDCE2D9FFE1CF2AAD7A18C73204D3CE4C7537B846C46577F626D85E62425E6D72D2BD30575E91E59E9E7341C50389E3D056A62FF21862E610DAA307228DD123F667DFF0B4EDD6F9691271D05037F1E0F49C85C4CD33EF9C35069961B71D589B666B6677D2E3DE66419ED1B7BDCCF37B97555116D5FCACF54FFAE7FA88DEA66DCAED572A8533B03E60C514469773BAB071C4AF7EA2283839B9834A3BC7E0A1AD7CF0A4468779171E8A00F3AE88D3E8627920D8109613749682CE587099B4F5A2BD8AD4DDAB140734416C56CCAC0AD5E378AA9E58DD2791B9028C2D5DE416A1C2BC552A7ECA45CD7A1C3555CD2F135CF1E4C0681A281532DA963A060D02B8B4E07080A0181A11030051C2A081E1E010C4185801091407020707E453A38E41C5010188C829A5E3696B27109DAB086A0394E6329443B9612820B9E7E627B0DD3A018050301AB74CD3F9D27DEF27EF1A66B06B9B4C47F4FA8467CBF7619984A269F70C28B0314E7F5C3F4AB89A6A60595461363AAF59F7E2CF4DCED7223E69CEC86ED77CF482C6F4756B4C345430A3F5043918431E6360E5A16D99696B8CE1BE9A9EFC15DD4C238A5EC60BD87ECAAB5A6602FDE939A09F610B8874C6E70E4E9C78A82351DD31AACFFC6643D9E15E25787CA6889106DEA8680087B51872F2847C180DBC4D7B51824BD815590C4D35C42412C0BD9AEA20DDB570EEECF7BE33F5F884501FF757BF044618C7374E729982CA603F70D178BBCDB9F6E844E2941A45877E0A90F2278768982F6508E59EF63C0E2B8E9CF9E18E26651507E91635B5F4B482F742765F45668E0D85B90563059B448A181032C74E95273B6EE8AAEC0DC440759F4CEB651F6FF75B40CE8B34DA5C70DE79C79C5A5029E5BBBBC4A27CB8887B010596DAD0F32D377FF1260C5377D28B3D8CF8318E7F7FE318CCC4B7A165DF8568A0ED18DE8609EC88F1B09FF2E371577A33145E19D4C018C08AE0C0CFEAE5A9A5C0ABFAD79260E5FD184F970256186E54D2BBDA1B0B1D759E597EE2B31CE76A0BFA899243B32503DCD71B7B76F1A4F3577F5B395DFEFE90F086EB02214083000DEE699FEF6F83FE804733825F6D3282991839B02E5B03CF24CA4D83D8C8FD407F0A77FA9636642C3D166BDEB3B3847D529787F7139C12E890DF19C8B78A28068C07BA31DFDCF274BDE4420B35ACA5AB4E3800BFB45DD55D1A64D1EB7F5CB182D1327FE92BAE1B0FED957B1966FCBF459ADCE09E2288297305C21F11B0C7352F02B02C8380AA10BA099AACCD3CBEBB39F636B8947AB1488511C8FC5A98A72D663C6157D08478F86BBE9728305DA1CD7B051308C82011F8A542E76E7D19DD8A11BF41381227341F68640A57C287FCB79664DBF093301C0976E7990EA2932B7CC406C157BF2BD84DB31C4E5450C98F7DAC0CCC689B8DE829F03440FEE11A2158327577227D1231732723357473D342896F51DE76DFABB0DAABAFE358898394F0039BFB8F809C582A24B15788664816A40CE3966DD892A84C0AFE95C15FAA5D8787A8609D5D73848CC460DAFC07293818A35431C15548D0336F5C2E2C1C887B2EC5AAD1DE9208FCF0D1C893ADF4E3DF214BBDB40D34359C33B9B8E8C15C75CF13279AEACC2D0519B52096DCF2196DDB5D117A5A06048F65A65138917705AFD23520039B8EBDFF8262AA83D8843259EE6BE0598644705CE8C8E19641FCE5806D725648E47397D7CAAF78D0B61FF496004F38E84DB32B43487157AFE4969D0511BFD2E344657685F72736D112DCF7EFE5392C35A5B207423213750A0711563AEE92D1750B02265A984B9FC16AB64510F296247A23E3915C1589A36D5D92903AF397CC91CCDDE67B1F430BF39D7DF542E38E912FCA7C0B1F5A93B09A3E705EEAC8928F3B013D918ABC9919E42EAB13F37CF12382B270DEF271C35DCCD6E2649B062B967F5522484C3870703DC36843AF41C410C0DFFA95A8AEBC9BF6DC6125E471A3B7710239A6A245539C6A2037F650D00402B572259DA9FDC07AB1891CE0C01DFC9B4D008F8F6636681A0B5BE0061A97FFB8A9152A229CF782E3606CB63F40E7264B78FB9C1DEBB224A6DA715DDED8262140C1C42CA7E6368B506D12D1CDD6ADCDC1CF9242652C674C3B1DE4DBA175A17A1D50121618563AA147C72FE0F3D5A35E30087854E257210C9513BF2D88F55C5BFE8BA72443BDB16324AD24C8FA09AFD4E9F3C67D43495DA9145A33051D1FD7CC3D4C8931D0C7C49A64B3E97E722D9FF04F0DCB75739F83F7C13E1D30C0C8EFFDCA3D87B81F23E661BDD2631A4A4C3D094F0FA6EF9E71FDBB0ADBFFF2837B1DCA4277FFD96FCA4AF782002AB6C2EFD30CF9E62FBE96D04507B73DAFDA786277AAB0EA03916FDFC55F9D6EB99EFBAC896817F44965179307A91CAA39CBFA69DE0CC7008FFA9F106B0C0A09177BDE823136C4145AA3E97E40C111E8AFB5100FD831F8EAC828BFEF00EC49A1FAD8D514CC0CF2746C6EC46EE571ED328DBF352F6806A8300094644E8F885219763A33E8629D9A227B1AD72E3A31D6F01250E3B1523DC3E590BC65585C28AE6C65BD75E9A026647C014D152B8F9673291A108F37E95040C2C57ABDAF0EAEE7CB4E993682CB9D1C9F7FA15B0E4BBB68F5E624E66FD89AD511708D7B5CB313251554615EF0B26B514C8B4FF4C50AF756D7286248F54D2CAAE76D78788FE177E9DE5EA0F96888AF727D744B184242B14BB24B4A32F1394B475780BBC62195DCF722AD37A78A4B20A52D32F940A0618901DF5A9541D59CF7BB507CA4496185282B52699DB69C10DB7BD2B20AF4453D30E7090F01A58297DFF253D7B563756332D62BDD1CBA9521FB462079ED3AB75DC35C71E6AAB8775B2BCFDBB693F38FD0DA3FAA94AA7105635669D645CFFE263B6ED67A9CBD534BF2918B959F14F7A617A796577D4F31F671D75C2C2128DC0490B2A458C07800860E8248BE8788485515DDE9B68B63FEBE8BEB482FF2E783F32BBD23E6757C87A6EBED3E4693A742C811A01B18F8F81C73DECA5DF0982781ED71364F108FA10DE82449F9C839FACADF8F3529D49565A07A2A64E50BD315A2779B96AA6B8470D02318D27A0BF0F6D0DA6EB36D1FD902737844A9EDDAEE92EEF94BFA5FEAE6819BD1AFF5F8A9CBE700F5ED1D0D8B3CC1946E56FC99560B6D1FF1AB3E021F3506E8EF1F6DC7FCAA0299D00B7B17D954204FDE8F4FFC1C6E78AB1AA88AED70CEBFB87BB5F06A89DF53D19FFA3D4EC1CA494EC7CA00768BAC68A39B2E43302A5FEFAAC7A82BA837664D2599D821A2F992347788CC9B0E0BC7D1473C57C1A0017B69CF8D4BF31E8DFE1E95B1422400EA3A3A9C57F7FE8373AA045600FF57B564808A5578D302761021499E010BFDF298D85B8C3B17E9D564B9651ECC2522B2BF96F6F088F7B359BCA416CE9100509962D26FDD6CA1D074B771BDE52DBE8FC306EE508DBFE9090FDB32D11273ACBAE8AD509A50F4A57AD3A503638032A4529BCA1076F50B231546F1FC38D674CAD686B97EF9220145FE1444E78BE16C20650D1EED5535A2050F0BC90231A749730427B1ED74E52D93CC2621881A6310ABACF70EC65F60FA51EDB31F0C4ED07412370EE6DF46528CDB452790C765F2C3FE9B4F093F21E5E53D01BB0357CAAA48FB11D300DC8018C022DD66515174C8F99D3F21148F072DC1AF6C10438E5AFCDA1A38A436CEACAD80CAB0870363408979B9C6B0AA073FEA16E55A2758E28E94D9F9DFBD2B73DA276C169396BFCA7ADED0F464DC60C57F10054E1AF6DFFC4C7CC2F54923AF2B850A18C1F6406D50C3779AB879B788F17B0E91789E1070C0E8BCD9B37AD19CA613F3244F86FF1A0D82441276E9FC2F72C1EC27053102410F83B089CF993C09507BB81C03A10E9FCBF0E909106C72ADC8439595432D25665AD94D210493279B01882BB1DA5343877D74B099657C45E2798843976D12EC01662B5DA114583FDC94C54BF60D37F9553649B9539E8AC390BC55C216801C226186538671319D8480CB7F3BE40663815A08D640A7DE2DE4EC524930877CB896FFD5BDB22767A467D8E6AE5B4E42C9D32ADF1C87D068A6A9C22CA7FFB3E7CC5BA64430EFDE52BB5EBDA05152F1056F2ED5C2061B782DA80180503BD4BA49656E9F899545B660D07DBFD052774CDE7171FB9AD2BCB42DA42DA352080B39336055FE6C5A3A6197AAA7632430FF9C2BBBA3D05FA2C61CF43CE14F018E3D83213D9DE012B43A34479287EBCAC24088750B9136FFF7181B3787642E4FC4FF1450D9FB6C55EA20F228AFDE87389C8933CC6346DD80DA15918F246FD56A6A297AAE44CBDD1F5157534453E3200588AA342215EC3ACBBA48320121259415C181C81E8C072BC90D1DC40DE69BC1E9C4DE669A9A698467A3877C0AC1A9533E4E6D3BBF9E0FEC997A087917AC2C5044676DF0F786E67A4804CBE3CE0AB5B5EFB4FC2E696E58BE6F0BF0C1E28DE74F1789CDC04692B3C7270BF8E8201835DF87E85569CECF51E57568BCE9C6FD99757A1980FD200410C25D9C495271440686CF56B7AF460C4661D210F4DE9A4EA954FC876CC11F2D3932017EDB426A1EB43550854CD67DFCB15AC4FEAB7C6958187A32FA9560C83EA0A179C397F95D539F01E01B5FE5885BFABA8F9388AB28F88BCAE0C88B00AC3BB84239B79ABD43EEC389031FE6DF974FCC69D43F8B55C5E1D4E75A970B0992D3DE0B8D056FCA977A8EA37BF43D8B2D1485E5C9D95BD8E5FC0B348676129A67B259DE7BD7F9FEC718A36C6C801015510F2A72FAB6EFF27E0636E95A55E970679205CC6376EFBFFD1FB8F3F185EC5F203F313E1FC0A60940F28B2B450234AE9602DAFF3C0B7782140928603F47EFF564C5F417393B58AFE8F1F55C1973A13A47D1E8FBFB9F8126842BFF6D0AE798EA58C3B9CFD8A33539F07140F35FD87F4F4779E7B525B7BFFCD67E391292154F07FC0662F2295F5BC8A6F1B72D6C33DD4441F5B25DC33D185F9B0DC4F51185FC939AA68229187AD553E8F74C53F081D20B265F827C3A1AE4CD0C2FA1B180406A1D84B81412888FF2BBB831588020C42FAFF048983359814E0617B6277F93897ED044A9756D55B5C4A506855D15BA4F8A5EF4870EB34B8770908E62D88E49F0D18FE84A75C92A7480B7E97F93C990F91BE12A5E4AC42F6E7A5761BED8F700FB531E0238799A6DFE4C28B81BBDF112779A83487488C6272A1C987C66CF0351707CFC7ED7B644C0F602597CF3DEDB4AE1AE949FF3447606AB5DFDFD54D73989C9D6D3184DB63A15305DF9FAC4C7F911E1C96C9DB76F05E72CFFF064102AF9014F6372330BC23F1DA47BA3718FE94440702CD0B2FE60738DFB1D5A63CF2FF6694857A67C0090F0712E79635E3149222CD9005263F30C7120D0B9E89F46306F176242065CA31460D6E782A3F381F572BBE2A620FB9544B9F4A9C2970850018D0FC4B56A0CFFB232D527A7D973DA293BCF026F838D2C06CCDFC7F51813ADD3613A0D2D2A1760D3F9E0AE7AA643B3DFF3EC982652834FE592883146D1A7E8834BA35D4B9F22EE753A16DE9C49C6E56C3F9D7CF457BEDB37F18786640A52165319ABD81AC36816223AB9D37E97853B7CEAB09A26F7AB88715C273FDFBA37D71F4F73F8D9A4EDADC134F989D5BD6ADF4E7A5433EF240D8BD3B599062059BC1BFC79F0E7AE82E74CB23BBDC3D7976D91FC77F27BC9FD7A359D32CF58C6AD59A88AD0DB54DCC2EC0E8881E7793F497D01F759A6D3B2E7DF2F4FE0078C1B1344D9B67A95368DD069765A94785DEF87ACF40C082AB7E8444C1A9FDF5741B37249F7013C20D784E791B3E3F8C232BFE21A2225051D365BDA5CDF312274EB5F06770FDEF2DD797935B75ADA1A48BF5DF70143DDAAED6CB924F26ECF75703AEE725D5FF13DDE228A31307D7AF0F7A755FBE9963CFDE2140D13101AF51325AA6BD68890FD3660A96553874F5158FCE11A2DEDA0714417C2B8B7A7C336FDCB9424CD85F83F60163E6CD2818E280B49E55295ECDA6E1D91AAC232A67D956258C399F24DD3F86C34C9BE2F61D3A52808028652B193AE5ACC208C33A88AD9D75D2F7534CAF5F85FFA773AFF0A5DFA472C444F58F8836DE890C69069708CD0E7958142F3127FB9D5F626C9F04311C9131D4051C6763EFD223226C6ECFFBE1D7AC199AFDD50FE1880E84FFEFABF9DD546BCEABE037AE941C3C80C0427D68B97E6F96CC04EA2AB6DAC4766AC9D353BC297C1959B013A9B8B5C6A01758072E72FA01AE963BF6124DD360B949BC66E86887708726AD22FACEFA02A3E1C0B79215BFD5BFCA9184B55447466BC12105D176D6C488F754B881B4E4197C9602DB0D9DE27D94D9FCC67760FDE752C7EBC545FD1785AEBA16DDDD87F81DABC513C17FAF70ECF98F8CE98E0DAC17541F01276DE2872CFCCDAFD7B71C6972A403F60D2FB8B2F970A5F6950E2D66DFCBA588F6797AE432CFFC6C47E0711E93555767167B746FA7B3B3A8341153CC63FF504F395189775154F42402586A8A5668118CF8B7F2ABAFA3571C0DA9F425CE7D43B11820CB65497863422F35FBF6184A310965888D365E8CCDD8F5A4958004089055F15528F8316120102E8D44B19D60ECD36EAC6FA53FC9BCFA6C050D21FD43656DC799F347D6DF64775B42533A3E6E6AF99DE1641119D0BDD1C4B7CF17BAD90BBDFD558C984E94937198756A381F9F18EB5248E9914027DFC4C03DC0A28D6B66E9F80AC0C284C9FE1A077BFA41FA0604046E72D67CCEC0ECD0770E54F4AE97B55C968E476DED11A00D3C697351C9E96528E389BE15EFCA49AE035CB04C41A4A5F88EB27FD6775D092B4C718527FDA56AD1C2F594E25A622B13E661A33217463F58CFB610AC4800B5E3F8467F00B5FAE3439D2CD299949CF4C90E18680A76B9CA6E4D3B030F1BD14E1EB30A424F76BB706D5A102DD13F189C00FDF4DAA4D0484105DBDBA3FAD9E6C57B2DD54B074D26D4E656938ACB034EEA1FF68DB86979D480F9F17B179205C8915B85FE8537FA5EACEBB7196296708EACAD252A10CC1635FFC992A6E2F57F7C289D3C49E87D6F2B34AC933E7255DC30974D34D75C3D32528E88188E028A31E15B786163FE15B388E2CA4C08083E37318E788BCADF720E45D42F53D8458E6D6747B73EC3C64DAEB6CBBACA97826F59173DBC685737FB5FD88CAEE5D738C68FEAA3C1A5394E0165FE3E9B8F74B5541827ACB77A84B0563A2C07C77ACD94D3495036442FC16FCB095D889FA8587612BC317899DB0DD223D20B5B511F163AE0F38FACC30B5CD7FF679AD5979669688DC9F8656D31E92A0358B429B387CF26CFB8073740A265E7121BCF9DBEF6C82920215AB5EEDF6FB46ED0034CDAC738B641DD318BE6D7C92CEF828AFB53B1B327A7EDD3153E995C654BA3EB259CF791FC9EF25246339FF1CDD337273A11CCA4339D547216DD46B233480CA89B0C40FA993D125E61CAD60C2030961620E67F819F3CAEE039E5B1A2507E7D90F4C5FB8A3D8FD617CC0B064D25787EC9EE2DE893873D7BE82EB465767A77CC94F270E7CDB97F69AA5265B6E9E2A8C8FA78A46B00080D4F01D18ECA384D43871E8AEBF15E04672F5FB2F2373E7A0E6D6CFDE78A4420E6BDFF4B346AD152320717BB692EC8EEFD28A3F7C3C3E171A0A7CE2666A74D7E4E5845CB6EB06F6A64235E54EC072682C6B795CC98042302567FB0B22738FD807CBDEB2459880EE7E8B178F817C85782945DE58E756A168C197FAC280C47925FD44B0A0CFA7FB38B42FA5001B5AF735FD0DDB2FAC723FEA9CAB7D0AAA2E2F7B22A76AE405DC33E3BA717021EFAC76A7479E30D45479B6FBA7F6F5DDA6F5D7F319C27E5713431F5780DBC19F312C0BC708F60CE682CD3388417DAA667606A20CEEECAFF0A28593C6732B34192EE69EE12C893BCB0DE893DA38FC5744A8855B97EEDF50A1E9B79B5886EC22E88E802690BC012D1015370A547C22E3EFA6002DCD43C3464169F0F587D6DAEAE22F634513C0D3C187AE762CD3ED878453780FC1B899CD5AEE3837A979E08C8A4C52819BDB84528B8EFB5C7B59EFFC8B31C1E873D266989BFECA9641EB9568617A7B41687D3FCB77E3F22A27C93BBBC315CB048531E54909E1850B8DE888CFF4C745F100860206134CE8B518F3E22E8DAF47B9067051C829BBA158724DE3B73B55B18D9A82C1B8089503B790D3B8D80A51EED58FE2A49B7922347191DB91BA5B7CE781DFB0E4E13E7B5A358158B4E6973F97BF1A57D2124B2BC3BE2655C09D2B2A27FF4D37E2361B0F8950DBABA1FDB0609952A4F0BAC0E48B7E7539227417DA01B052CC562F4788AA25CBCCEB65B673B2023E5C1B719333678812A033B494801E893B2D9147F62AC9DFAF1402C5B3E67085373922337937D19FE2BDECE8765FEAD0C0EEEF641626EB4FB2E0F4081E1CBCFB6BB3C932231ECFA8EECD1F146FF7B9F05D12C66956573F3B4B6D233DF3FB5340DA613B2DC343BCDFAE486701554EAFA3733C534140767E2259B2E08C000A554B03F919B5CDF80D22E6179FD9793AF512992475594BE75565BDBB606312280463CBFE2D2C91B3A670EE6D6FC6BDB5799ADED9B30B6077293C2060B0BF590BFCBE3B6ECBA4E537FFA33C14996B9ED4637B7762C9F0BB56A8AC931E823349FBE8C70E953B7E3FE5D97427BA487327D1ACA66FCABBFE29E89ABA97940041866E852F3EB49BC90ECBD1788D2AC37F2B4F195CE7C48C767D4DBCEC0470A6483D7C15B4D676B1DCC94BE387C78573C603FF0ACDA77496DC08810023723A1BC1C97FA812205CA41472BA5ABF59CAE22E5EE96625E589FFB3B898CAD04C731FF8D52024AE666FB7DAD0A7822BDBF31784ED6C68369BEE89358A199FF5720D4A8A55DD29A31D36B91263B38FAD3F9BD8F81D63E880496CE3B99FC150B8208A6E10B594BD4D3950DD056857EFEC0F1638CBBA0D414DC9D50956E3DFCA55C47C7491EACCCBC0388990B0E7186D26738D9114AE18BB1E23DC7ACDC247F17E49136327381FF97EB73B88D3D7AE5F0891AA83EE7579F9D591E195966851AC27355CE2A2412110E8D42B512E999B5E469104197E883BFC9E506885FAE16CE3C15E571C37300617090F54405A71E298BD5D7FE3BE101514DEF801717C91FAE2B19084F2273EE7DE4B197934F19E7050EF288737F20F3C493D8A1B7AFA40A4EEAF50A2B0E02CC0494FD21D1A7511431A6CD103135D51F1E8BFBE46C8DAC3E0B43F98D2299DC4EC1212427048D7E8B00C5D8BE768BD4573B2A57F2FB7C64E1D3FAA0A2F26F6264F485B5DCD4D139E8A80314A8BA7EC6C5EBB506D1F482024DF876479110DEFFA8BC62E5C2AA44D5B88FF3A09684E127201088A9245E7AC66A1A0C83019C60A92F6A1CFA18B282B199043536EFED8BAD2FDD658C91DA67125E5FC356B3FED8447CC62A21DFA00EEAC75D0E2A5D07E324187A602A513AE0752AFD0CE31C0471AA3B5CC8612FD545ADA7FE7E98C44CA5CE8DC7A9CF159E7674A33AA39F443969B68386E39842CF9338A9A07256E147CBE8370231D26928B770577F51A806D4E9F7F27A612569983867F390B78803C39BC0EC24F824427EF4B4981871EDF4AEEEA5E8AEFA15285B00A690FCACE5D97447041C0FB678D086CC440463A6E39BD8EBB3FDFADE8DCCBE4DB1CFC7D4BC16EAE8332CBD6A0128966A2E6844F41801990654680A1719A4E03E864246648F112B25988D31FFD6D1526858BF28A8E777E34B2C0C73A95A60BE70A5014FA39E7DD4388716A76C6F1C2B95F97198883E5E051A151CF82700FD080AF0FFCC60915EDC636E63553CA9E5616FB19A14061D79A7C3E8384AD39EC426E9ADD5AE75D18F5484F57530DEEED6588AD4B1021852930C9B82DB5167E08AA7B39A5B8F04D5B3EF68693445E6CDC373A790C5D6EAF6CB1CAB975E2E4D5D6D13D85240C42D23AF1FB3F988B99C856A83CE3FA077C07F23B4ECE379EEBBAEA2995F49BFE057AE88F8BC5B82167E28DCCC076DE5A662E474125A4CE9B752D14ADC379D9434D97A1024583A423C5BE34D4EB17EE9716555ED1C0B08D3622DC5E66268105F92D3F926DD4C72C14761266B6607179102F65AB87B6789952ADDAB988F6D1F95311A0FFB7EDDCAF78F1F8478910357A3C8FFA130073D3344517D7CFE5F21791D37C78F485903D9E103110C3142DE895FE9FF417992A31F642D0F6D95D80A1A03D5CDD4763E58517BFBA6BFDC7D0946F9F64A1EAA2C8AA03CBABDCD1663F373FFE5CCBBEB60448A9119434A713076A90105D7E8EFA9E9B754CAFDF5EB8A4470BCC58061A75CCE0BEC27BBDEFCCC9F97527CEF22F7D4237A0B1ADC3E51D2725C6574E286A81F8349DF6326702F2F8283FABDDA94AA171947E725BEA7C40AFCB79331020DD6DDDC4F8D0CF3F949666E8E501AF1846FE7592B8B46CFFEF562F0C34FD88617279034C670E3D4D06CE96CE93AEDE7AF6B2D4F354A6AA405575B9798F12E1DD1CB0BE9C214BEC606B67BDA6FADBC4C4FA7BD968076296471C8061CAD85236AB863412010080402814020100804D11A8C874C8302418192ADB818A2FB48D040F4678046AA5E062B3388C61C98C60C04F83CD84B7D447FA5A182DBCDEB0BC01DCF1C5BFAA0E4803A411980F396BF761A64524C4121E005D8CD82C64BEA4FC333F13038ACF5B75EEA52B2C3E195C28F0444AFD27E6015198989E49BE9596B1E33194C991B49D5FC5FEAAB9D4D94F97155AD5E2BF18125B14A02D8B8A4063A2AE9476DC2967A85693250FBC2E2C0B9AF8FBB6A372AA025667DF613AD0AF9FCF37E80FC95D70FE33F21C7077054F3A2EA6B357A0D1EDA7787E0C9CAEF3AA36DEB2C36D8ED376A9BF5002681C4C9C2EACE3841FEEDF7374AE4F7F63C6BBCF5C0AB77AA8AE5194DDBB2B809D92F57229D3BA035BC6174C603BC0A53F33D9E769008BE40E7616427C1671715B6D10482686BED6EEFE6E9E79CB71EECD12CD8D52F3D49132531BA29FF0979B8C48F393134C5DB86959942792437519E9CE30FA6A37680ED2D92FB3A073C5F4DFAD448A151E84C9D602874E47FF22B0F32ACE68AA08D045EC5031D18B5FD44601E8086537194FB45FD43A34C934CD0A256A500BFE3E33CAE4D532F34F91983617BE1EA639C4CBA1CD4B767A80E0149D6B46A5AF5922C59FE0D0D84C2FF2835FB2AB444177CF737D4406072D82A37EDBBF96F8ED5ED22DC04BA7CEE902D7D1C845A648BA1D78E65526C6292FB26443BFDD803EE6B77F766CA07C6A697CB6FEC461E35F5A69EAB69259FACD038606528F010707B7316B7CFC31C2F1EAA0F21C9228782C641A6203D101EF876CBF4FBFDFFA3E5A4E5F51587853FE2279F5E1A2367A7E195ACD9716EF2C93A2E7E166E000A3B57924F7214CBE981FBDC23DC4606B6FB8587BE3B927BB40249F7A8DF82E30781134368AB127EB921A3F09CDF790FDF9EB99F1D40A6D1A45A31BAB0B2B1D08E6F579F504BC5265C44F479A60B0819C658DB1964D1E7D1DC7AD3BB270DBC1021DC9FCAE9F5EEC15BF3FBC227D9FBCB7B47A7D43C7AC01C0CA667FF61312456CAB3FACFA4C334FDD07400CFC7B8BFB03830BE113ADCA7A6FF449258ADB1E81CCD14B3638EE81F75881179DC4924ECCB758057B086891FC80DB01922D5B5A95917C5AF91F29A53F29926717B913CB2A9A7B15817797F829B99805F5E40F4929341CA2BFB16657FC29D0982FFE7C982786AEB54ACC2A59F9A02C3DE88350228158D67A0D1029E5ACCA4A5F92AD9E8E67151A5319EAAE10D50EBB09DA69B1138B3C736BE8DB4BA62C4DA64779C60F44E95B55C29D8F4A4FB21F5E7CAA1DBA5A7EF3E957395A5331477CD63B43B228FA22F0989A892A4355945C029FFD56427EB04484D3B852A81B542E5FBAB6E2F7A203FBEE5269B91BF879EEC888C54CEFF8642716421CEBE611F93F697573077BE3959A7316DD94E12CC2EBD0BCBD213F9948A39C79920C02E43269A080618C0844FC7EE7FCF15D65CC2CA19A7FF10A16C70DC53132475C629FABFB85433A007D0D747121CA177A71F192FDA02125C3D6883EC6C1FE7D5998E26EC7FB191BD807118BAF06D834D848D42E8FA544A6C6395AA32445F6D201390B8EDA21D4534ABE42A53876FAB6E42B5CCF732384262A9634E884304B0967230FFD2B893EF7DFAC07CE784DF8EB377A937FD29C9905FB3BA741CB8C02166ADFF727419F10310CCEE627A431ADE4BDCD464911B29B132F8B60674B7A65F1AA311097AED9020429E0C2FB189BC0281401E82103C273851982D1472F6266D4EF4F92E198B097D27898DD65ECEB6F95782996BF4C5E7D7F68769D922A6C4C0C5EAD29A920AFB6AD2C89ED7ACE3797E7F20905708AE799643C8EAB19511E500EFCEC11158C07040C51C146C149172A278E9C349FED7F18847FE15BDCEA460AA6D62A54AD3616BE325952C8FDD3633DA5389A95D6230C401D3C8ED8AB4F1DFEA86C47C7F55B5F8D0FDA4F88E8D376A64FB3F4E0F5E9C5B4D06087D8BB694EF7DACB6E310E5DB4C9A591412C39969D5636FE639047EC4C67416CAD6EA1DADB4224E54E8FFDC73AF1F9D1517D5AE19EC05E358B313C1A835EFF53C16397349A9B52E1FC9CC4B3FF67C99AF96E64695C2B768E54677A2F6FB8937B06276C9BD8982C1A31BD5BD1CF0D9965C5EA9DE98F8B662E8D729297A8267BEE6D76D943927D24C4B2AF190858F3D12707685A658B99412D8AEB53E88C52F2BE43CF1557C191F0B755614274382E14CA527EE7129934230E58CC65BC18E7EB258A788A42769792FAC2AEBFF2FA807094FD29C67FC36398D8E434C48175FDC4176B4F1C40F58215B9BF206EDF561DC6C958F8CA7A01C53271FECFC6AA8440990EC5024A82286DF548BDB42F4CCC713E03C417F50D90E5427C6886E7C89BDB408FC92900482D75332858A39328B1A5D7457EA0EE68CC949B97A4B569DAFF48F8201864DB32C82C6CFDF43A389B268451C992AED662B0A2583ED24E49B7A26E1E0320064B8A26266505476599CA426B7543AEAF56565F61045F674A73762CA7EB64A300804028140E0AED5D09EA8E4A6069FA55CD95D45EB51EC26CD10A1B81195273B5173215D1EDA45F4CB078112585EA61FA74A70945C1E123ED5165686EF0A57849AE578D2768CFD9D9B3043D78444A8A13A6D6162DE83C0DAB5B334D6224EBFEF2B8A362A6BDAA8CB8DDFBECD1F25E02447BB21744A05FEFC1D1C7C472FB69A3D14911B91513D422FE93E4C4BDC36F6AB8E8BF06852227086361C47A131E78F4C0C29AD04AF0E89D0B19B6F3F7E3E0446C1C0BE9A6B07097F1DB47AC5A8C0F66F93CCCA582BA6E6336848ED49E71AAE34721C507E5722741868450911425B3CC5986EE468AB13B2FA4DCB14A72FF418B855AF89834336E11E216BD152BF56EEBA51310594FCBBAC2CA7AD11B2909BA8ECCFC241D05422691A70A0BF29D748ECC41FB78D17751FA343DABAB33C096284CA615C24F43D68BEFA4DB876D0E2596FB0114E55B553DF34184E88D440D7632650A404BEF303C4E1C80FEBBA8B0CDC0795F10B17A231C25B5FC279D9E51F617B16EE83F1A93DF09F61313ADD453A5B18532B8802FAE06A476C8DFFA889DE46EC53CAF925DB90BF988F5E383B3BB5B9997AA9D3C87A0056210D19EB50563A6383F48F9F4972E16952B989C57F30601B6AAEDDF60EFD767AB699700F69D114D5B108F0B45245D89E66E510B6036531F3F798B0454365CBBFDF1BBE6BEFC1AA73FB8876F164407612FCE78B83224CF5F1F70E7CD56311D6CF17589F24EBAD3CE9EFF0E19C2DDAF87F7C8A4C4BABAF332E3F1923FF6940712A3FBD1BE04400B84101ABB4115CF14BC7FC1BEDF65EF1187F3CDDB4AF08C4EDCD19159E67DA8BF349BDF0AC3F4B0B3683B5282F6DF7A78B2CCE50EF2A12B961BCDC55F9DFAB07D88E5C43F827BBCB17157DFEDD79A709F03065A832E19A3180ABC48083E8442F44C5D47EA93B1ECCF1D1D56A7E867DE0827FF30334AA95F4E17B2A9635C0EBFE40180D51F5D125550907A0058DA59DD9BAE625BD738954FF41345D23456227F1DC528CE35DD4C14CDBE3572EC1D9BBAB9D049F5DEDF3C9E8F20056CAA197D696ACBBA9B6B61671301B44539ACFA58B94803C7686E282F9F1A3A2519EE9D4037391FB87844F49437487AAC95A5CB5F8F842A7A7C8C673A49CDACC3F56CF91D3B6EE171F188D186B7BAB17B927E4AF9B5004E7B9B9EE67DC5A1201BF945D330DEDAF10A412E5F691D446915D71566B03EB6AFF676DB4E99FA2DDE9C965E9A754DEE665F447DCEC92F20FAA87718C246619342BC62E8A0A37B5390ABF4F77C40FDE9FAC360091D6547DAEE2165A01EE3CF31614234A1B8AE0B4C2C4F03397CF32F2CE79F485E29D3AB637D0B6CA7479F4C80BAB7E19C8CF712A50836F23978392FB635029DD8D26787B55CE814FDC84193A3A947CAEEAEACC31A1A55B96CEF247F323BE8975EDAA9CFC072EDACDB49437ED0F5DE967D9695C7591E55D0AD7075E2BBEB416CF5B9661FBD2D43A5DA80521529D56270AC58BADF3B837F3A9321D6AC5752C50F26D232D6528046080A2885466F9379739B4103961A45B32076C5655E2FE877A21C9B2DEF43477D46240A8B3D8470FFEFC4574273D1B27D2E5AA77BDFF3FC1B4A4FC4ADDFBC0E8B5D926C03ED7671AE9D9F7FDA719B3F78FAB534BA0A36E0C51D04077EF2DF4845C0746148B2C515F5C35E42227FB0F290D418E28FE79E6D09C52433253F54F124B81E7B6F1506A2087C0174132D2902588AB4448CEAC84E4F34B27249F5F202ACDD282AC89C80E57367C2542565B03BEA5B18DD4674E2FD712349973A554F703C42C29C3ED2E6E4C9F1EA6303C0FB6F691688F7F07D3F49BB49C6EF91FE2C199F7A1B1A4EB8B02D7168B673597CF37FA36F13C6ABABE762119A29788272E9AE17E33797067A0C3D268A7133139290377001CC61729307F124674E670A23F3FE8F2A1E56B242BBE59B5B2FCAD49CDA2909AB8B449F561D324CB42B2B143DED18B344179E54D0B5E92761B404E20F1B3B2A9FA638CF4E2BF4252542C79FDE65131B83493DDFF52DB833B2A9F6A5E2389F098B3A92D7500FF61F92F1593E92097F579FF11ADAC8E513D135079C4D912CD4FB6E7A53F913EF03673AEBA478B2640652D6BF6C3C76B640AC355B3B9CEE1C0A74D05A5F02F72F011F890680DEEF67780466EEDBB6AD52981AB78D947514C7A2B79858582E1364DA99F4DCE1D833B736681D590B856DB02CC45508CC2800BF05138566C41B1D6753E0EC640217247A23876B19AC95BD8A75AD513FFBC4B40BFFE673C2042F01A70E167383C99F83C815E0AEADCC0C5F8F5DBB04C62A83A0EC66BEF87BAF31667F9966DA133D0AEAE91D197624C65F74429D16267FB1DC1682D7173C56E5C8221B298F933AA59F1B0DA9A07D02DF327473FC559ED31811223746EB9ADC04AB687E5454DCFBD1B0DCCE279EE9CA300DBF97C746B026B22667D886C3973E5772535E7160CD3F54606B925B787FFE9B529CED927D6791996689E452B4CC9AB084028C8A68F607636E016EF0A476BBD7C2EA445D0A1E28F1AC5EB73F6AF13DC3DBF694BF322DA27D8DA4768C9FFA0E74B35AF83C0F0C85F1483DB5C866CAAC83E375813F28B185F241DF7E23804800CFE4EE2EA081EC22B6FB01FCD8858261FEF3D67701CF6422E29DCFFB76CDE37F3D13E9D028E2E5FE182300E7841A2D7B2CC7D7DE5AF4BA361FE8E16614D6ECFBE7C6753158B11F35D2B58941D90AA6C400BA918C67E0E335DF6C5C74F77E05841E5F87677F500474FA559DEC14BB48FB2B55FD892FF20302FDCBC80534DEAD093EB596217A573D1439A4FBE0E61328E2B44AE7A1E03B07691EF59D1C31B4ED0B4E84B48637E4739895CE8140F53717625D4E249216628DA07D1F9937D29AC782039AC371A0C2B6D5F68270977C9D6884334B0D5C1127A1224257E7666E0DEDC01C4467AA7C585F351AE199D6256A0AADF6B962D5AE6AB8452ED4C1FE6B3DAD6D9D8DAE09E7E8EBDAD2BD5223893BA185A65231E58DAA54151DB54670CA243E69738C2D5F4044CDA1CAF4DECC874CA87D0EFD790C5CC634C99031332D5C84004FFA78AAB2095D8BA66933BF2A9967C7931585ED7DBCEE47368C6C3756FC00632EB5ED18DCBD2DF56547E0FF9ACD781D9FDDF87BC3BDC43A957DAB7A5815AF057257C99AAE1F03520425BA36DAC25FAF26816F245EDF49AEB631B47B7128C2535B4D25AB62673D093C70577C03D825BA351A2CA7E33B9090BB9CDDF08136BA6F05167F5AAAE4AC64084235F94B5D3474D91C2FD1300953F6F11C89E12C7F0226BF8E3352B6D9E35E17717CF5C83AA6A49F8A43CCBF7BC3EC711620DDD001A16F03751171B06781F875D83DB391C182768045494463D8B3AC36EBED25BD021782811851C0E879ACC9C9F3D2F88D98EB5CC46EA27171CAC5DF0204D5F03C64E45110EC71BE91B47B77F5C4F0AEB5D76A95778228E329AA6BCF2FF311F40B0AFBE2686688A70B50FA84FE9088EC8891007E72CA70E926153664CA6430707DFA62969E93EBA8A74BF1B511BA7285F0A8EF0C3E12748B97C295EA6AF3D117AD4988D4AE9A6719633FB05E034113A068849F67E4711D1035884F2B8E0746445DDC54430EB15BE6F575B64E5C06625F040C454DC7EFB35ADFCADB965344D0F7C4A282B1DE743FEEA79CFDA5F8AE3131232F33F24610360CD097100CF9EF044F7DF65795CAE7FE769565D61AB1F2D7BCCDDBC25BD7D890B6F0C53E6000D349CC3361E7B6E6759A1EEFC9377070DC5F2A02F2D0A7508B54BDC8D667CDAE94A6D871F9A05D90DDED26C1D148D34E08D6CBB53E6FA61AAD4845BB42FB7852AC8A72C97FE95748BB8E2D97C8EB593E055EF83D8B9613140E18F57E44CB5251B98480D415EBF014F2203276D02A5210FBACA06452B7707341A02AAB07071A245C9734D5E372094DCEADABF4A0C5391081216DA26402FAC6A178AEB6F0B3CE3BDEC21454D2EA22866A8D19B5FFCB35E6DC24C1594CB312DCEA93BA7709EC9B05078EA604AA79668BED9CA809A0C7D92C835AD1DA528939427BDB4639E593BEEE7C8A5B2FA6F1CA6BDBF50CF67DC2463917BE05D613329FDE76B48F625F41538B2A7ED21606DC887363F4A599161B1CD9564E10C6B96556C8B8D8281D87F91BEF0BACD0E5CE834278B75C10132845F96FE1A3F64F6990F5637A4486B0158A0A1B8C47E8198A291363F92064D4158A74F0D6A71403373F6E87B7F367318F61D651383020827AA8A4BB8EEEBFBA4352347DDCA23E0F5BD8DC67365DD59352E10B8E064A5E12C2904E281D0E9C1CD32AFA257CB2E44B3D76E22E63E838BC2360C8C3BD15BA2C52A19A721C09327FDA69C605784D1B2EC80F7C797933F5F1E3E1953CA7EB968C448CCC0ABDBC46D6993207D6DFDCEAFB01902714020CD1C89BA4A0E0B8C61EC45866AAF39F4414C105904F67BD91C8F930BBC5004C878639D939934ACEAA4E573A02107CFDF73F5E43E9C7C47F6EBD6541FAB58F09ABC5872A613B29E08C1FC1210BDD90604044223879A2EBC6E20110C6080F5406BB5F72B83C792F65F42ADDEDFD3B9A7DC538E8FA7CE964DCBE889C991DB80E4777D45DA9E8F1A8231C41F4D3E2569529A5EE154E66018D38CE1E4C1B92944C14B2EC5F45AE447D17C8477F0D06730D3A361BBA73B1F864B8C6A2B6907FAFEC1D9336599E4985CD793B24A5E22562FAD4D480B7A4EAF288EDEEE5620422CC0A7E8C9AE8E104BE2CD398B87C17EF8E6DA892FE83F2FD8477E76CA3E49502D067EB22589D03608DF71891EC678D6859CB67209A46E30257E90AAD2251A1A84403358CE7D5B4A1C34A11AD0E1DCDF2C88FD28675009404FE8E5082C5865F3CE45EC5B9C0B18FE7206B218D2BBD77E14BEE13D1EE6F1BDBDC06B7079AF150E316493EFC2EED787A56D5023EAA9E594D592F40FE4459CF41AE58FA4C8A211DD3EE452D849F02ACAC288DB00A5548D4CAB564C6933B8ED07A1E2150511F349D7A85579C63601BBA4997C4161935ABB33FC2691BB0CDE88DD34A557807EA4548FC532D188286CB49430E67E74B10B991937FC86CA3F2387597D1802B0BF4EEED4C2B2973F15BE7E08070A197A50BFFB264AE270EC2B7DEBAFC9EAF4C1A9E911333B235CFEF60803ED78AD03AACDF601A3190FA3927DCA9F21B71DD8ECBB3B585D10070E7A3BB37585D8816B7F12E95C938F78BEB3CA526542AC5F9A67F7282FD790C94FE4E2B3417FD3C5249308883D813B1ABB4C832F55914C6878A91F5630B1F74DAEF16232B0351EB7C7365EA3E3968175A0CF9F50D237AFA305717411FEA7F5665FF4B936B9B728AC69F33C9BCDAA6169991A605F88909CD7884CFBF0AA56DDB8EEB193CBE4367710F33F2817773ABB31C72F47B6C4C390BA1D272CD2631E7C52C07ABFD895CB6CD393A243B424FA1AE43AF17DC7DEB1FF53717B2F5C06807A2E6D234E7BF0F7CFB2D1C07F3DE5E858317F506D3A2B4F1CB884C6D523659978F0638F4770CFCACE018988C194914A7F9639184FD6BCBD6DBCFBA06783892CBD89F7EE57F30E54D99DF8918765852E567353C19E0E338009CE8B1859525BAB25B67EE1B2DCB11BCCE28698BF3007A21DD46FF7C83E5D66D5147FFC9EFBDBB4983A3DE7C53557A6B7D59F7EB44BE5F920DC3F2D8F7FE80869B593197DD6D8354045F7F9E8D0D92D7F73ED15DB3A45135E7067DE8B70E8B07563CD823DDEF10182D3163D33C914AE3CB90E6A3C777EDD57EB8BECC20EAD14A7651B98933FF4784CC9BF8784EA48400F2771D72015B54BFD7F81B83F0C42A2FB89CB8D15B215A6D6FDEC6964A93510B6A8639816B9B06724FD7C6AF60CEDD4669470F317E88F2F0591C814DBC5D07861FE37F926BA87BF4315006DA7877092B34DA6EA2921FCA17E91736F2B33A17775AA15057173338D1B8926FC2804ED3D4636D9EF61314FDB45F0CB05A14273D0D964930D853C588FBDC0E34FE94EBF57BFC9C2CFD6C84D98A12EC17A115290841E6C79B0C415D44305B4CC1E231D5DFE4B3F30F7DE7CCCF943421F1F628F76B5E12456F7F893D7D96F86D2860ECFCC032648412D8197CCF89A43A935CC491BA8A5A5C02FC3F43688ADF522F92A760E26190AA330C0868B53FBE55FC16F0F75B15F52F95FA8B57878104750C51775DEF27B531AE88A002994C194D8AF668833F84A05C35AB293C24CB71D95D8FF9F8CECBC512A7D52EFF13A1E733109127F835D5C226B2955C24B3E9C917B87F6D08EED678E2C378A32E3093406D8EC837F173F9D4730FC46CA7F34C010E0A6666D8EFA7F5A3A77C34C911FE7A9D3AD997B0C57B850D077133683430B0A4803BF1F9CA94315098140021E0403130437E0D324DD67C444FE01F4335A80752FD3FD19777D7DDE5CEC91897E3A3FA99ED3B90797749E9A253A8294EC014D8DC57F5CCA3FB2B5530D635707FE802E79ADEEB7976D40E346C9495262AC3E5C07652406FE656EC335A8C31FA15B89F1850FF708C68E41DA297EC2E5FEB51998C4145649AE54D3AC3B5E44D9F26DED8F4FEA2F05651C1B6DC4E0310FC460591E7B118819B0941BE2A522842363DB7D7F4742746011B98347945A4095241EF838C710FBDD027FC38BB63C62097F1F7F2742AC0122F5317F29CAF473517F4F34C0D1B11155FEBF2EAE61EECCB547E74738CEA21FF91156C78D2BED69A3412FE8A08F743E04F6B1BBE01E219F62C0BE73CDE477F6170B863A48E546BE7C26ECFC9A698C85BC34A1D42D8DF9747BF80CEB83C809FC237D52D7570834D88277BFE0BEC1648806BBA2008946552D23BDE6544E2F2971DAD2E629E261260D44E3C6BB9946895ABE6713112F55AA6B8EA96FB87B70990BC3F5CA791E40472F50E81CEEF799761E04FB71879340A18BD83B9832EB8BA59FBC27EC7910243CF215481B08E83D911D918147F6964647B964289D95C50DF40198465414844F7DFEA51E37BC910E63B567F04EA0FC8EF997FB1A9C61B5529C48282E60B5E10EB8FB54AE76DCA8457F5EE423C4092F39BEA81A338069E88343D7A1E324DA6DCA107D6241AD3379A2BC65EA8430A4CBE622C6DDC5DFCDC3584C13370B2D0C649F9F1E00457155C698FCADFAB8129B3608F1FC2235974C27C1E4654ED36D49B3AC2C353AE0E217B5D5B798FD717454FA4989AFF4F4B623B9451677E55124DA23D19849886FF14A4D3C22C68D118DFE2D001F8CCADBD742F1818412F7033FF29D7E60AEE5C7BD339900721C3E23A593A94DF88D15D793D761264A344D56CC2DD232E35248ABDE24A9FA8C5411FC3A668B9BF6A41D769A24D9636DA7B1195C3B0D9404DEFE8A03CFD49472D855A57BBD494837B14D6A897F8CCCB1DD1B24E92DB2DF8A556DB252E14B3F4A7D0F253AEDE87452BD92FDAC5E2B440DDF9EC58D019088AA670EABD924244B287F572D27D51F8B4DA36927D50A0994DCE0D32C8EA2211ECA3B00CA19DDB717F3E0848AEA91E46ADB2EC89BBA7AD865C7B5C4E3CF96A1CE53E1D9F75AE7DCA3F3A2A2C0124625D44E982E46A3C71E9C289EF6883B5067000FDAEB2851BB2FD2E323BA959FED00EF29E9592719E3A289351AA3F41A60830A2D80BB04C3A09B9C757A1918C081364ED0C68D3D6F01F67CD6EFF96D4E14B7AEE17E88C6EC3E5AD66021AB99C0DDFBCE6E726E6B19F19FD9FECA80AF41868F4B44839A98FE82C1B5A52DC756D4E90F4718DEFFFEE1868AF07D96638FADB16FB33730C622107E654BAE6192043FEE7A75FBAABFD4C8E67D4320CFC5DECA4214D611E67D9A0DFFE95C8E4A8952E15A3801AC05BFFB8359E0AFCFE4FDEEC6D54915D3B9167658C6F0299726F2D79CDB554DB6278315AB73DEB870086229E037EC07B39E9997A55D619C68975A1494FD296EB8E47396B4D1AD8BFBBEE874EF839F5C047AE9C420B08B338A75F2104B81C0465FA55292BE4740D0214FD0178F90D347613B437C64F1FA4313102B7DB3DD7E9317ACAC47223F63B25AF7B119A099605C80EABBD2FA519A7EAA0115473520FA940AF1F5BAB6B23416A4915D26625B2107D07B9C7D106C795D634C80CCE2C94981100F787BB8FEC973A49DE5310ECB6CFED277584362FBB1CF0DFE35693C407FE0A8AB1B10D9FCCC26C9EFE337D48D643AAC3CAA1AF2D78A818C64D8A4326D679F74388691E700F6837B047BC580C1A1F1469895315963477B4712F885075918B7D3B1A64E1F1B3DD5628E9FEFC5F5B37F1D71F17517A208111604694E99E6FFF0FEEEFE9FCC37C2A00999D7D4C8F017A95C318884D303C0B588319EA0D81B17EAB233A28E5DFEF4034C194EE41AA878F3067EE88F32C873DB08D596A48F3ED590716B989306646601865CDCDFF76E95AFC6A8A80DFBCA3D34A66812E8D799E07BD90B26BBBBC36A0DB067EED560D7925E6E3E47A91A4B26724EDD5CD3439C6B0F05B99E7E910AA4AD8A82D6DD2E66926F27B141462D9E4D836C8ADA69232ACF40DFF3CF3F405CF386387DB556B6BEDF73E754A876367BA44197BA9FD9DA7537FEA1EDA482C0710F18658ABCFF4689287F6E732F71849CA02DB942B5D467474A419D8D53474C38BEF71768C0DFA9094205879DB2A75CA6DEFEDDCB7A5D01CC0D7F7D0616050E3CC507CE8E71F2BA57CF539F7666206100D98F55910FD20DC0FDD831E073B158F2B313D87F611F60AC0F7C882CCCDE70626338DD8F7B33A1F75628FC3D631204D550BE7062BC6339FE76C718DF9DD3ECE56CBF5C291846C140A55EC0C879B34E4BAACADC967CDD41C4666643140FBBF9E07B2F425820DCC603409AD01EF0A89389FFE4A2A3B6F641ED9614E6A25033D1CD080E5043AA396C3DB7E6B5F50032F5EF5FA2DD802877E635DCB047FBF7B5198B949FFD8C055CAF9970D5A3DD0CD79FB22FCA7A53D80A87363490E9286FD6466EC43C20717921F5CEED22B9366424300D848611083040A2B282BE8BFCFF505106EA493282D8E7CEC97E4B3CDC0FB2A84E9C9795235A0380C41BC1E6555723F553896F86B24EFB57CE56AB21E128C4C3E75D66B8E07CF9689C77560D82382EAE2354A454DDAF96C68CE7921E1903C1BA0C624FBAD544707E7540018828050F0B7CC65CDCB7CCEA9D22F81905F8B2B0FE0DC914B6B7E36D836B4DB03F6320B3C88AB98808C864B621A4B86C88C4792947A104441301C2245F8031D12EED768CF7226583E08A2C672B1860C0DB9787000E2C8050F4FA726950A016882713F5A8B1C81BDFD13E25391CC3C00738E0E5B664DFEB3DB86A4627859189B08E1C91835D2FF22B8373FC6551F70BF370D4428A55ED9254140925E664CBE374759B42F377FBDD8362FA2C65FFE6AE047E552EA4B56356CAE7D3382B4C8B99731D8C571BFFBDE60CD1E7B046C2FBF9A56681CB61418C338EBB643537B38B403E77BDE4BD66D3F16A810140CEF029CDCE80CD5246F3F1A1C0E508A2CD3DAAB623085EC13A59850C2A680370F2E80D8214447625BE805010EFCFF6B71F6ACB0AC760FE7BD9495FC6033E992CFF75466EECAB33DB6E69288EF688F3B00A3B899A3E294554E8500114F277043B972F71C2C24E301A48E8E0C93C74C5F3B17BAAED338B7C7F99ECFEC77E4F1019CE6691D9242532C93B87963C460A87613A65E64DD59AD18339DB9F35C561260CFC9FE2E61CAEDCFFC12E978900D2A3ADA1A7486AF4C1C48CEF0DFD06BFCE3F453CE6E4D048D6BEF9B14854662F7E3C53EA59E211C9B321C179EDAA3FEC8148A6E827F24E09AB73BEAEF34F17CD91683E02180BFF1B1B9123132BA13C3F9269E8882FD3B4BF9CC011C0A26386826EC6AA46F2B222F4F494FFBB86C3483DF4CF2F1E7A60B914C9D432AA1EA99CD278313AFD7A995DA772C47D1D34C5400003C2F5FFAD74D28FA6F10D0C0B01E2B9A8D9A4BB8FCE114CD6FCA15B5EDDA9BCF300AE93269890B21F1114E126291E99A4AB005DD49F523E44F13C1CD03AA759BB805761D45AD2B596F13896C6BC35D14C8551993EFD921C11E279B1415401F3E0BB751AEB72912FFE71C6ABCE579ADF92C0FF29C3B166E766B60BAB8ED8245F422CDF84F12069D9B8EB4FD1623B2BF46BC9279CBF74AF49F9F333AABABEDBC86C54ECCBC02AFA7AFA82BFA23AE2F19B44145BEEDF49639FC78AAD7FB16B7E2E4AD7F98F22D1470078D4C0CDD5B4051534C3D766DF758617675E2B208993D1A8E342A5B73D05BEFF14FF990F74B69381AEE2BEE0B8E08E088020BF670D1C938F2EDFA07C8A1BEE7EA51A4FA4A9979AC747B2E9A67260DB66A5FDF949B7245890C46C9AC860CA999D6BDF38CAD32AF1BF21D1AED86F3D37CFEA0A71795A797504C4146E9FA448C1D932BD16655094CBADD1FAA8942F1E9487E00799E7490309061830368DC1E1BDDA56894AD6C64E43920960454689D74FF5334BDBD0689C82E55B004FE67DA7F5676C5CA3FBD2328686865BFC81A1AEE119609A7ACA62802D8DA1154D57ECA737D02098210871C878B953A01855E1E55C75FE595B91D9ADD0CF878918FF28828F0A09CBD560BDB2B1B8CE1C926ED654A6A4650BA09186D5CFB7D213674CF6755D539635B2DACCFC9B90E6A71C45363755C20E29D16C12D0DA0E85511870B2AD874C6B3F91BE5E71A92F2BD266F65365D0C644738B4180FEFB92AF6F6222A040E32C5CD438DFE17E56714C44F57707E4B785F1E91B2F79DC48DEC65E3A4D84BC975603F75019DD94108B781DA51F4330DABD41CFE2105FD15F6436AB34C83A82E021D73158AF1004090E0E2B6AA46C318A005CF979792078D8823D61925EB679CDF92EABD5D7D5BCFFEDB363088B627FFEE230D99DB5C21E28E298796D1A707A22BBFC05615949FE966E8089BF4D5FD6EBB22E8A87C65CEE54E7F4061AFE4E161CFFF152C3D533EAF58F6B2DB3527189E91BB17644F328C615F994CBBFB3577E87836C91226E2D4C7BDC317A7D09A7343E079F021DC6AF1FBB45110C047173EA5450F66CCC90C58EBCBA7484E2CCE25CA28CA7784A8DC5E8B09D460F80D92D32A37588C70437982BD4EB7C621406B865A042563C35570E3AECB592A68CCB471AF8F81E09BF0EB454195B1678E3A001061D1DBFDBE9197EB15433740C5ED1749B5FB0CBE15202C9D287623235A5E1C27D58BDA5DFDEE18512A104775509C65C5749DBCE152B4D99FD336C448CAD44318A9AD2BF8D5E3C0C825AD4D7387DDD0ADCDAC18F9A9CF0D10BC238400DFF742CB364375CCEDBDBA153D72BA3C0B2F955E827CB6C6A2A1A65D782581B60001ECB0FBF61389ECF30E28E5E3017FBC91DFA1FB94F5036FC14D357715EE19AE47FB0A9B1D2986375C5397612BDB86B0CB3E1ABAA19DD2452BEA4FE990A38E016EC921B0503FA19ECA7A71F568077BD63EF73597A54836DB013C76A6D623F394738F2B489B8CB7C47C4040F50E96A56E4AAA4A77750BAEC750A5BA41B25DEDAE6AB692F169F926F1F7DB3F5C6F15DE9B10B11B815B4A0AD514F7780F2485F06CD76862BE8F6813CEEA26F7C65DF66EAE1B178A074449DFEB28BC6414015B425A6F0EBE5B8B7049917DD19E07B334FBA9750C24238ABE2B3D11EFCAA9310DB5ED152573529927C4CEE9DD3023869B21B62F6928463E00B843880F6F283CFCAD866C080C689D17597D0717F86BDAF87A957A6B99A62663A8A712FE01654035583AB4090CC671AA4AD526D3F19C16F565188AA7EB34154BC7022B5241E21A4C723C20B160E0B6E8AC2EF097FF3D7F771EBA00870A0402B6C6246A583375781C972059F5EF55588A4F79885FE3480DE672E635A259A95221CAEB004556ADA3E18F410B39E36CD26980B459E832485B2FF4B6709EA1664ACEA55E631CFE7AFAC79F268310650901F007DD173E07E5FB78367B3495F9C5F261D8C3F7329ECA537162DF17E590D52E33BB911353716925F361DA0F77E8285FEA87AE4BC8D85C52E073BA9CDEB252C1516539ACC5E8CD5CB15DDE86499DA5555F5E3CD11B18F53FC9A0AA15F2C63CA4B8B407EA75876328CF1A6FF66204D66BC8FC476356714C48FBB1DC8E60BB6FF482524AC36436BA537E7B799E719077966827FC79C55FD1F04FFA972B494BBF7A210241087504392BB8EB8C43BF27D140690794C059B22B0B4E6A095D548F71B7024FCFC496B498039631731CA630E613006AC1FF4D1FDD230F48929404FC820BE50D960E50CB4BE79023568B52FBB07A5AE6C21DF280D3B0B0FC2723626A8D3F441C0BFC9AE42668B86CF8934E4D915C0AC4A7B877E21F64508AA319ACB6151E7963779D19BE6D56FA46F1D673FEE2DCF03A3D1CFEA00C67AD4632BE916DA139FED32E489FE933C3199492F2AEB8081B2AFCB9BB530F681EB58735ACC12A92108B905D7B32A85A1C86E14DE3B3DC521984C91016492827E0E31AA9EF60F3515597CF208471583CCB28B407F508B37DA5060E55D86AD1D5C43869B37156E75733AF4E59C8E520DE34EC65D111004BDD6B88488FBBAD6730BF95B076AE021A9D29195020860A6A456994F3172C476E46EB18858CF684470CB9428BAA210E1AF83E23514D5654594A9D157BDE3848796010731F7EAD94A460AB281E843D45C82BDB6A4ADA23DE04113387CD748EB6EF4300567D15E10CC6F7E6744795CE4B1ECE9EF523AEF588E0B422993FF90A4497AE41F605CD488D8987B3D179220A4498D6B88ADD3B9FA7490211DA4F741D1D8CBA12B2376FB5936E38FD713EC9BE76FECA93DFA207275558232DA855CE958658CA049E93B49708F92F7F75121E085A61919ACA021FDC09E82750452BE1E11F6C52D46E907D61B48116A897036B847E667A8D8C8DB2772FEAE19EAE371EC1905CFBD1ACB2ABA93ACCDDE95573AD4AF8B1E951E4E3A5E27DD60266173EA1811044DA3BC1FB409A0D4031B91780D6BD2A78FCFE942C6AC5721279E7EF500D560649876F752D41289A825D7A411F59E090417B18432FAE4E218AD2F625454EC81A5B075BA778A5522914F8FB26EF6AF2A9C5A179879741A6A08ED462F1E767EA1E8BD711040248A96B3CA68F965FA1F202C16506EA6158528FF46C1E42DB5709CE14028424EC45AFAC113B8335278955547A871DABCD71234804FC28C552A21B96C848644DE07C43A546262E82F814D9AD7F472097B738DDAD3D17C7D6E150F8DE29755821C77E0037065AFF741D3A85AA30BEF082D30329A80180503556886D569B7F8995655A9EA444899472BC7CDF3552CEDE1AA498BF3144367298024AB79D2F32F8DE3CD51D2CF26E69DEAEFF1FBC8A55A826FDCA83FD1E3B5306EE1C52AC944719E10BD9557A47F1AB6C66F55D6014544D8A7535A434E8AC4F2715E6DA8684FBE91AFBF67B1602E3572B7F35D2AA5CB7507CC3080E62B2846C18087FFBD4EF407C6F60B5908852F51FD4F095E1C04A0E9C79F428766AE3E2E0C07801BCD102C2B848178BE36AAB237DCF092A9778BDBB3DFCCF5E4186DC9F6E14B3D7BBD69B887A776C2281AAF44A2B6E23313BE20CC042A2D7E933C4171CE68449B5F882C18FAF8D73C86FCF85D38923962140694E0ED5AF8FA711FDACFDC1C7511C09139DBF508B6F538B7062E81163542138D00B8BB17A9AEC8E1C30B4503EBBBB40FA15CE46ABBF37F5831CF36603D1E3E6925, afterDelayedMessagesRead=778082, gasRefunder=0xe64a54E2533Fd126C2E452c5fAb544d80E2E4eb5, prevMessageCount=59442932, newMessageCount=59443064 )TransparentUpgradeableProxy.STATICCALL( )-
Bridge.DELEGATECALL( )
-
TransparentUpgradeableProxy.86598a56( )-
Bridge.enqueueSequencerMessage( dataHash=10002EB1091BEB75E03FC91B9386EAE4DB77695704C77BA6BB6CA2F604D39AB1, afterDelayedMessagesRead=778082, prevMessageCount=59442932, newMessageCount=59443064 ) => ( seqMessageIndex=156107, beforeAcc=2AA8835EF48C556C36927BCC8D939D83FC7EEA5925E59854958599A7F7CABF15, delayedAcc=15A7C645E1A315E5F3B71E1F0F66C45AC33E0A9B48D6FA64BF790437E73FB36D, acc=F885FB6CF06D01B1FD8234578D7E34A11A0C874F7DACF51A99195A50D74AD80F )
-
TransparentUpgradeableProxy.7a88b107( )-
Bridge.submitBatchSpendingReport( sender=0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc, messageDataHash=179639E209AADC114C04EF6E29BC32F64818A29F8026F7ABF57365FF9D193A17 ) => ( 778114 )
-
GasRefunder.onGasSpent( refundee=0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc, gasUsed=208337, calldataSize=99300 ) => ( success=True )- ETH 0.071861141692223342
Arbitrum: Batch Submitter.CALL( )
- ETH 0.071861141692223342
addSequencerL2BatchFromOrigin[SequencerInbox (ln:154)]
NotOrigin[SequencerInbox (ln:161)]NotBatchPoster[SequencerInbox (ln:162)]formDataHash[SequencerInbox (ln:163)]packHeader[SequencerInbox (ln:318)]getTimeBounds[SequencerInbox (ln:300)]
concat[SequencerInbox (ln:319)]
addSequencerL2BatchImpl[SequencerInbox (ln:172)]DelayedBackwards[SequencerInbox (ln:345)]delayedMessageCount[SequencerInbox (ln:346)]DelayedTooFar[SequencerInbox (ln:346)]enqueueSequencerMessage[SequencerInbox (ln:347)]submitBatchSpendingReport[SequencerInbox (ln:365)]InboxMessageDelivered[SequencerInbox (ln:370)]
BadSequencerNumber[SequencerInbox (ln:174)]SequencerBatchDelivered[SequencerInbox (ln:175)]
File 1 of 5: TransparentUpgradeableProxy
File 2 of 5: TransparentUpgradeableProxy
File 3 of 5: GasRefunder
File 4 of 5: SequencerInbox
File 5 of 5: Bridge
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)
pragma solidity ^0.8.0;
import "../ERC1967/ERC1967Proxy.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 ERC1967Proxy {
/**
* @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
* optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
*/
constructor(
address _logic,
address admin_,
bytes memory _data
) payable ERC1967Proxy(_logic, _data) {
assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
_changeAdmin(admin_);
}
/**
* @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
*/
modifier ifAdmin() {
if (msg.sender == _getAdmin()) {
_;
} 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_ = _getAdmin();
}
/**
* @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 {
_changeAdmin(newAdmin);
}
/**
* @dev Upgrade the implementation of the proxy.
*
* NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
*/
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeToAndCall(newImplementation, bytes(""), false);
}
/**
* @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 ifAdmin {
_upgradeToAndCall(newImplementation, data, true);
}
/**
* @dev Returns the current admin.
*/
function _admin() internal view virtual returns (address) {
return _getAdmin();
}
/**
* @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
*/
function _beforeFallback() internal virtual override {
require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
super._beforeFallback();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)
pragma solidity ^0.8.0;
import "../Proxy.sol";
import "./ERC1967Upgrade.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.
*/
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
/**
* @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) payable {
assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
_upgradeToAndCall(_logic, _data, false);
}
/**
* @dev Returns the current implementation address.
*/
function _implementation() internal view virtual override returns (address impl) {
return ERC1967Upgrade._getImplementation();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)
pragma solidity ^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 internal call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
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
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*
* @custom:oz-upgrades-unsafe-allow delegatecall
*/
abstract contract ERC1967Upgrade {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @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 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @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 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(
address newBeacon,
bytes memory data,
bool forceCall
) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 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");
(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");
(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");
(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");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal 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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}
File 2 of 5: TransparentUpgradeableProxy
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)
pragma solidity ^0.8.0;
import "../ERC1967/ERC1967Proxy.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 ERC1967Proxy {
/**
* @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
* optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
*/
constructor(
address _logic,
address admin_,
bytes memory _data
) payable ERC1967Proxy(_logic, _data) {
assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
_changeAdmin(admin_);
}
/**
* @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
*/
modifier ifAdmin() {
if (msg.sender == _getAdmin()) {
_;
} 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_ = _getAdmin();
}
/**
* @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 {
_changeAdmin(newAdmin);
}
/**
* @dev Upgrade the implementation of the proxy.
*
* NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
*/
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeToAndCall(newImplementation, bytes(""), false);
}
/**
* @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 ifAdmin {
_upgradeToAndCall(newImplementation, data, true);
}
/**
* @dev Returns the current admin.
*/
function _admin() internal view virtual returns (address) {
return _getAdmin();
}
/**
* @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
*/
function _beforeFallback() internal virtual override {
require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
super._beforeFallback();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)
pragma solidity ^0.8.0;
import "../Proxy.sol";
import "./ERC1967Upgrade.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.
*/
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
/**
* @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) payable {
assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
_upgradeToAndCall(_logic, _data, false);
}
/**
* @dev Returns the current implementation address.
*/
function _implementation() internal view virtual override returns (address impl) {
return ERC1967Upgrade._getImplementation();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)
pragma solidity ^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 internal call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
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
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*
* @custom:oz-upgrades-unsafe-allow delegatecall
*/
abstract contract ERC1967Upgrade {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @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 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @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 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(
address newBeacon,
bytes memory data,
bool forceCall
) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 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");
(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");
(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");
(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");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal 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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}
File 3 of 5: GasRefunder
// SPDX-License-Identifier: Apache-2.0
/*
* Copyright 2021, Offchain Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pragma solidity ^0.8.7;
import "./IGasRefunder.sol";
import "@openzeppelin/contracts-0.8/access/Ownable.sol";
contract GasRefunder is IGasRefunder, Ownable {
mapping(address => bool) public allowedContracts;
mapping(address => bool) public allowedRefundees;
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,
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;
}
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
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
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() {
_transferOwnership(_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 {
_transferOwnership(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");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
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 4 of 5: SequencerInbox
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {
AlreadyInit,
HadZeroInit,
NotOrigin,
DataTooLarge,
NotRollup,
DelayedBackwards,
DelayedTooFar,
ForceIncludeBlockTooSoon,
ForceIncludeTimeTooSoon,
IncorrectMessagePreimage,
NotBatchPoster,
BadSequencerNumber,
DataNotAuthenticated,
AlreadyValidDASKeyset,
NoSuchKeyset,
NotForked
} from "../libraries/Error.sol";
import "./IBridge.sol";
import "./IInbox.sol";
import "./ISequencerInbox.sol";
import "../rollup/IRollupLogic.sol";
import "./Messages.sol";
import {L1MessageType_batchPostingReport} from "../libraries/MessageTypes.sol";
import {GasRefundEnabled, IGasRefunder} from "../libraries/IGasRefunder.sol";
import "../libraries/DelegateCallAware.sol";
import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
/**
* @title Accepts batches from the sequencer and adds them to the rollup inbox.
* @notice Contains the inbox accumulator which is the ordering of all data and transactions to be processed by the rollup.
* As part of submitting a batch the sequencer is also expected to include items enqueued
* in the delayed inbox (Bridge.sol). If items in the delayed inbox are not included by a
* sequencer within a time limit they can be force included into the rollup inbox by anyone.
*/
contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox {
uint256 public totalDelayedMessagesRead;
IBridge public bridge;
/// @inheritdoc ISequencerInbox
uint256 public constant HEADER_LENGTH = 40;
/// @inheritdoc ISequencerInbox
bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
IOwnable public rollup;
mapping(address => bool) public isBatchPoster;
ISequencerInbox.MaxTimeVariation public maxTimeVariation;
mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo;
modifier onlyRollupOwner() {
if (msg.sender != rollup.owner()) revert NotOwner(msg.sender, address(rollup));
_;
}
uint256 internal immutable deployTimeChainId = block.chainid;
function _chainIdChanged() internal view returns (bool) {
return deployTimeChainId != block.chainid;
}
function initialize(
IBridge bridge_,
ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
) external onlyDelegated {
if (bridge != IBridge(address(0))) revert AlreadyInit();
if (bridge_ == IBridge(address(0))) revert HadZeroInit();
bridge = bridge_;
rollup = bridge_.rollup();
maxTimeVariation = maxTimeVariation_;
}
function getTimeBounds() internal view virtual returns (TimeBounds memory) {
TimeBounds memory bounds;
if (block.timestamp > maxTimeVariation.delaySeconds) {
bounds.minTimestamp = uint64(block.timestamp - maxTimeVariation.delaySeconds);
}
bounds.maxTimestamp = uint64(block.timestamp + maxTimeVariation.futureSeconds);
if (block.number > maxTimeVariation.delayBlocks) {
bounds.minBlockNumber = uint64(block.number - maxTimeVariation.delayBlocks);
}
bounds.maxBlockNumber = uint64(block.number + maxTimeVariation.futureBlocks);
return bounds;
}
/// @inheritdoc ISequencerInbox
function removeDelayAfterFork() external {
if (!_chainIdChanged()) revert NotForked();
maxTimeVariation = ISequencerInbox.MaxTimeVariation({
delayBlocks: 1,
futureBlocks: 1,
delaySeconds: 1,
futureSeconds: 1
});
}
/// @inheritdoc ISequencerInbox
function forceInclusion(
uint256 _totalDelayedMessagesRead,
uint8 kind,
uint64[2] calldata l1BlockAndTime,
uint256 baseFeeL1,
address sender,
bytes32 messageDataHash
) external {
if (_totalDelayedMessagesRead <= totalDelayedMessagesRead) revert DelayedBackwards();
bytes32 messageHash = Messages.messageHash(
kind,
sender,
l1BlockAndTime[0],
l1BlockAndTime[1],
_totalDelayedMessagesRead - 1,
baseFeeL1,
messageDataHash
);
// Can only force-include after the Sequencer-only window has expired.
if (l1BlockAndTime[0] + maxTimeVariation.delayBlocks >= block.number)
revert ForceIncludeBlockTooSoon();
if (l1BlockAndTime[1] + maxTimeVariation.delaySeconds >= block.timestamp)
revert ForceIncludeTimeTooSoon();
// Verify that message hash represents the last message sequence of delayed message to be included
bytes32 prevDelayedAcc = 0;
if (_totalDelayedMessagesRead > 1) {
prevDelayedAcc = bridge.delayedInboxAccs(_totalDelayedMessagesRead - 2);
}
if (
bridge.delayedInboxAccs(_totalDelayedMessagesRead - 1) !=
Messages.accumulateInboxMessage(prevDelayedAcc, messageHash)
) revert IncorrectMessagePreimage();
(bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
_totalDelayedMessagesRead
);
uint256 __totalDelayedMessagesRead = _totalDelayedMessagesRead;
uint256 prevSeqMsgCount = bridge.sequencerReportedSubMessageCount();
uint256 newSeqMsgCount = prevSeqMsgCount +
_totalDelayedMessagesRead -
totalDelayedMessagesRead;
(
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 afterAcc
) = addSequencerL2BatchImpl(
dataHash,
__totalDelayedMessagesRead,
0,
prevSeqMsgCount,
newSeqMsgCount
);
emit SequencerBatchDelivered(
seqMessageIndex,
beforeAcc,
afterAcc,
delayedAcc,
totalDelayedMessagesRead,
timeBounds,
BatchDataLocation.NoData
);
}
/// @dev Deprecated in favor of the variant specifying message counts for consistency
function addSequencerL2BatchFromOrigin(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder
) external refundsGas(gasRefunder) {
// solhint-disable-next-line avoid-tx-origin
if (msg.sender != tx.origin) revert NotOrigin();
if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
data,
afterDelayedMessagesRead
);
(
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 afterAcc
) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length, 0, 0);
if (seqMessageIndex != sequenceNumber)
revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
emit SequencerBatchDelivered(
sequenceNumber,
beforeAcc,
afterAcc,
delayedAcc,
totalDelayedMessagesRead,
timeBounds,
BatchDataLocation.TxInput
);
}
function addSequencerL2BatchFromOrigin(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder,
uint256 prevMessageCount,
uint256 newMessageCount
) external refundsGas(gasRefunder) {
// solhint-disable-next-line avoid-tx-origin
if (msg.sender != tx.origin) revert NotOrigin();
if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
data,
afterDelayedMessagesRead
);
// Reformat the stack to prevent "Stack too deep"
uint256 sequenceNumber_ = sequenceNumber;
TimeBounds memory timeBounds_ = timeBounds;
bytes32 dataHash_ = dataHash;
uint256 dataLength = data.length;
uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
uint256 prevMessageCount_ = prevMessageCount;
uint256 newMessageCount_ = newMessageCount;
(
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 afterAcc
) = addSequencerL2BatchImpl(
dataHash_,
afterDelayedMessagesRead_,
dataLength,
prevMessageCount_,
newMessageCount_
);
if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
emit SequencerBatchDelivered(
seqMessageIndex,
beforeAcc,
afterAcc,
delayedAcc,
totalDelayedMessagesRead,
timeBounds_,
BatchDataLocation.TxInput
);
}
function addSequencerL2Batch(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder,
uint256 prevMessageCount,
uint256 newMessageCount
) external override refundsGas(gasRefunder) {
if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster();
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
data,
afterDelayedMessagesRead
);
uint256 seqMessageIndex;
{
// Reformat the stack to prevent "Stack too deep"
uint256 sequenceNumber_ = sequenceNumber;
TimeBounds memory timeBounds_ = timeBounds;
bytes32 dataHash_ = dataHash;
uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
uint256 prevMessageCount_ = prevMessageCount;
uint256 newMessageCount_ = newMessageCount;
// we set the calldata length posted to 0 here since the caller isn't the origin
// of the tx, so they might have not paid tx input cost for the calldata
bytes32 beforeAcc;
bytes32 delayedAcc;
bytes32 afterAcc;
(seqMessageIndex, beforeAcc, delayedAcc, afterAcc) = addSequencerL2BatchImpl(
dataHash_,
afterDelayedMessagesRead_,
0,
prevMessageCount_,
newMessageCount_
);
if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
emit SequencerBatchDelivered(
seqMessageIndex,
beforeAcc,
afterAcc,
delayedAcc,
totalDelayedMessagesRead,
timeBounds_,
BatchDataLocation.SeparateBatchEvent
);
}
emit SequencerBatchData(seqMessageIndex, data);
}
modifier validateBatchData(bytes calldata data) {
uint256 fullDataLen = HEADER_LENGTH + data.length;
if (fullDataLen > MAX_DATA_SIZE) revert DataTooLarge(fullDataLen, MAX_DATA_SIZE);
if (data.length > 0 && (data[0] & DATA_AUTHENTICATED_FLAG) == DATA_AUTHENTICATED_FLAG) {
revert DataNotAuthenticated();
}
// the first byte is used to identify the type of batch data
// das batches expect to have the type byte set, followed by the keyset (so they should have at least 33 bytes)
if (data.length >= 33 && data[0] & 0x80 != 0) {
// we skip the first byte, then read the next 32 bytes for the keyset
bytes32 dasKeysetHash = bytes32(data[1:33]);
if (!dasKeySetInfo[dasKeysetHash].isValidKeyset) revert NoSuchKeyset(dasKeysetHash);
}
_;
}
function packHeader(uint256 afterDelayedMessagesRead)
internal
view
returns (bytes memory, TimeBounds memory)
{
TimeBounds memory timeBounds = getTimeBounds();
bytes memory header = abi.encodePacked(
timeBounds.minTimestamp,
timeBounds.maxTimestamp,
timeBounds.minBlockNumber,
timeBounds.maxBlockNumber,
uint64(afterDelayedMessagesRead)
);
// This must always be true from the packed encoding
assert(header.length == HEADER_LENGTH);
return (header, timeBounds);
}
function formDataHash(bytes calldata data, uint256 afterDelayedMessagesRead)
internal
view
validateBatchData(data)
returns (bytes32, TimeBounds memory)
{
(bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
bytes32 dataHash = keccak256(bytes.concat(header, data));
return (dataHash, timeBounds);
}
function formEmptyDataHash(uint256 afterDelayedMessagesRead)
internal
view
returns (bytes32, TimeBounds memory)
{
(bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
return (keccak256(header), timeBounds);
}
function addSequencerL2BatchImpl(
bytes32 dataHash,
uint256 afterDelayedMessagesRead,
uint256 calldataLengthPosted,
uint256 prevMessageCount,
uint256 newMessageCount
)
internal
returns (
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 acc
)
{
if (afterDelayedMessagesRead < totalDelayedMessagesRead) revert DelayedBackwards();
if (afterDelayedMessagesRead > bridge.delayedMessageCount()) revert DelayedTooFar();
(seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage(
dataHash,
afterDelayedMessagesRead,
prevMessageCount,
newMessageCount
);
totalDelayedMessagesRead = afterDelayedMessagesRead;
if (calldataLengthPosted > 0) {
// this msg isn't included in the current sequencer batch, but instead added to
// the delayed messages queue that is yet to be included
address batchPoster = msg.sender;
bytes memory spendingReportMsg = abi.encodePacked(
block.timestamp,
batchPoster,
dataHash,
seqMessageIndex,
block.basefee
);
uint256 msgNum = bridge.submitBatchSpendingReport(
batchPoster,
keccak256(spendingReportMsg)
);
// this is the same event used by Inbox.sol after including a message to the delayed message accumulator
emit InboxMessageDelivered(msgNum, spendingReportMsg);
}
}
function inboxAccs(uint256 index) external view returns (bytes32) {
return bridge.sequencerInboxAccs(index);
}
function batchCount() external view returns (uint256) {
return bridge.sequencerMessageCount();
}
/// @inheritdoc ISequencerInbox
function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
external
onlyRollupOwner
{
maxTimeVariation = maxTimeVariation_;
emit OwnerFunctionCalled(0);
}
/// @inheritdoc ISequencerInbox
function setIsBatchPoster(address addr, bool isBatchPoster_) external onlyRollupOwner {
isBatchPoster[addr] = isBatchPoster_;
emit OwnerFunctionCalled(1);
}
/// @inheritdoc ISequencerInbox
function setValidKeyset(bytes calldata keysetBytes) external onlyRollupOwner {
uint256 ksWord = uint256(keccak256(bytes.concat(hex"fe", keccak256(keysetBytes))));
bytes32 ksHash = bytes32(ksWord ^ (1 << 255));
require(keysetBytes.length < 64 * 1024, "keyset is too large");
if (dasKeySetInfo[ksHash].isValidKeyset) revert AlreadyValidDASKeyset(ksHash);
dasKeySetInfo[ksHash] = DasKeySetInfo({
isValidKeyset: true,
creationBlock: uint64(block.number)
});
emit SetValidKeyset(ksHash, keysetBytes);
emit OwnerFunctionCalled(2);
}
/// @inheritdoc ISequencerInbox
function invalidateKeysetHash(bytes32 ksHash) external onlyRollupOwner {
if (!dasKeySetInfo[ksHash].isValidKeyset) revert NoSuchKeyset(ksHash);
// we don't delete the block creation value since its used to fetch the SetValidKeyset
// event efficiently. The event provides the hash preimage of the key.
// this is still needed when syncing the chain after a keyset is invalidated.
dasKeySetInfo[ksHash].isValidKeyset = false;
emit InvalidateKeyset(ksHash);
emit OwnerFunctionCalled(3);
}
function isValidKeysetHash(bytes32 ksHash) external view returns (bool) {
return dasKeySetInfo[ksHash].isValidKeyset;
}
/// @inheritdoc ISequencerInbox
function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256) {
DasKeySetInfo memory ksInfo = dasKeySetInfo[ksHash];
if (ksInfo.creationBlock == 0) revert NoSuchKeyset(ksHash);
return uint256(ksInfo.creationBlock);
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
/// @dev Init was already called
error AlreadyInit();
/// Init was called with param set to zero that must be nonzero
error HadZeroInit();
/// @dev Thrown when non owner tries to access an only-owner function
/// @param sender The msg.sender who is not the owner
/// @param owner The owner address
error NotOwner(address sender, address owner);
/// @dev Thrown when an address that is not the rollup tries to call an only-rollup function
/// @param sender The sender who is not the rollup
/// @param rollup The rollup address authorized to call this function
error NotRollup(address sender, address rollup);
/// @dev Thrown when the contract was not called directly from the origin ie msg.sender != tx.origin
error NotOrigin();
/// @dev Provided data was too large
/// @param dataLength The length of the data that is too large
/// @param maxDataLength The max length the data can be
error DataTooLarge(uint256 dataLength, uint256 maxDataLength);
/// @dev The provided is not a contract and was expected to be
/// @param addr The adddress in question
error NotContract(address addr);
/// @dev The merkle proof provided was too long
/// @param actualLength The length of the merkle proof provided
/// @param maxProofLength The max length a merkle proof can have
error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
/// @dev Thrown when an un-authorized address tries to access an admin function
/// @param sender The un-authorized sender
/// @param rollup The rollup, which would be authorized
/// @param owner The rollup's owner, which would be authorized
error NotRollupOrOwner(address sender, address rollup, address owner);
// Bridge Errors
/// @dev Thrown when an un-authorized address tries to access an only-inbox function
/// @param sender The un-authorized sender
error NotDelayedInbox(address sender);
/// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
/// @param sender The un-authorized sender
error NotSequencerInbox(address sender);
/// @dev Thrown when an un-authorized address tries to access an only-outbox function
/// @param sender The un-authorized sender
error NotOutbox(address sender);
/// @dev the provided outbox address isn't valid
/// @param outbox address of outbox being set
error InvalidOutboxSet(address outbox);
// Inbox Errors
/// @dev The contract is paused, so cannot be paused
error AlreadyPaused();
/// @dev The contract is unpaused, so cannot be unpaused
error AlreadyUnpaused();
/// @dev The contract is paused
error Paused();
/// @dev msg.value sent to the inbox isn't high enough
error InsufficientValue(uint256 expected, uint256 actual);
/// @dev submission cost provided isn't enough to create retryable ticket
error InsufficientSubmissionCost(uint256 expected, uint256 actual);
/// @dev address not allowed to interact with the given contract
error NotAllowedOrigin(address origin);
/// @dev used to convey retryable tx data in eth calls without requiring a tx trace
/// this follows a pattern similar to EIP-3668 where reverts surface call information
error RetryableData(
address from,
address to,
uint256 l2CallValue,
uint256 deposit,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes data
);
/// @dev Thrown when a L1 chainId fork is detected
error L1Forked();
/// @dev Thrown when a L1 chainId fork is not detected
error NotForked();
// Outbox Errors
/// @dev The provided proof was too long
/// @param proofLength The length of the too-long proof
error ProofTooLong(uint256 proofLength);
/// @dev The output index was greater than the maximum
/// @param index The output index
/// @param maxIndex The max the index could be
error PathNotMinimal(uint256 index, uint256 maxIndex);
/// @dev The calculated root does not exist
/// @param root The calculated root
error UnknownRoot(bytes32 root);
/// @dev The record has already been spent
/// @param index The index of the spent record
error AlreadySpent(uint256 index);
/// @dev A call to the bridge failed with no return data
error BridgeCallFailed();
// Sequencer Inbox Errors
/// @dev Thrown when someone attempts to read fewer messages than have already been read
error DelayedBackwards();
/// @dev Thrown when someone attempts to read more messages than exist
error DelayedTooFar();
/// @dev Force include can only read messages more blocks old than the delay period
error ForceIncludeBlockTooSoon();
/// @dev Force include can only read messages more seconds old than the delay period
error ForceIncludeTimeTooSoon();
/// @dev The message provided did not match the hash in the delayed inbox
error IncorrectMessagePreimage();
/// @dev This can only be called by the batch poster
error NotBatchPoster();
/// @dev The sequence number provided to this message was inconsistent with the number of batches already included
error BadSequencerNumber(uint256 stored, uint256 received);
/// @dev The sequence message number provided to this message was inconsistent with the previous one
error BadSequencerMessageNumber(uint256 stored, uint256 received);
/// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
error DataNotAuthenticated();
/// @dev Tried to create an already valid Data Availability Service keyset
error AlreadyValidDASKeyset(bytes32);
/// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
error NoSuchKeyset(bytes32);
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IOwnable.sol";
interface IBridge {
event MessageDelivered(
uint256 indexed messageIndex,
bytes32 indexed beforeInboxAcc,
address inbox,
uint8 kind,
address sender,
bytes32 messageDataHash,
uint256 baseFeeL1,
uint64 timestamp
);
event BridgeCallTriggered(
address indexed outbox,
address indexed to,
uint256 value,
bytes data
);
event InboxToggle(address indexed inbox, bool enabled);
event OutboxToggle(address indexed outbox, bool enabled);
event SequencerInboxUpdated(address newSequencerInbox);
function allowedDelayedInboxList(uint256) external returns (address);
function allowedOutboxList(uint256) external returns (address);
/// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function delayedInboxAccs(uint256) external view returns (bytes32);
/// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function sequencerInboxAccs(uint256) external view returns (bytes32);
function rollup() external view returns (IOwnable);
function sequencerInbox() external view returns (address);
function activeOutbox() external view returns (address);
function allowedDelayedInboxes(address inbox) external view returns (bool);
function allowedOutboxes(address outbox) external view returns (bool);
function sequencerReportedSubMessageCount() external view returns (uint256);
/**
* @dev Enqueue a message in the delayed inbox accumulator.
* These messages are later sequenced in the SequencerInbox, either
* by the sequencer as part of a normal batch, or by force inclusion.
*/
function enqueueDelayedMessage(
uint8 kind,
address sender,
bytes32 messageDataHash
) external payable returns (uint256);
function executeCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool success, bytes memory returnData);
function delayedMessageCount() external view returns (uint256);
function sequencerMessageCount() external view returns (uint256);
// ---------- onlySequencerInbox functions ----------
function enqueueSequencerMessage(
bytes32 dataHash,
uint256 afterDelayedMessagesRead,
uint256 prevMessageCount,
uint256 newMessageCount
)
external
returns (
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 acc
);
/**
* @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
* This is done through a separate function entrypoint instead of allowing the sequencer inbox
* to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
* every delayed inbox or every sequencer inbox call.
*/
function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
external
returns (uint256 msgNum);
// ---------- onlyRollupOrOwner functions ----------
function setSequencerInbox(address _sequencerInbox) external;
function setDelayedInbox(address inbox, bool enabled) external;
function setOutbox(address inbox, bool enabled) external;
// ---------- initializer ----------
function initialize(IOwnable rollup_) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IBridge.sol";
import "./IDelayedMessageProvider.sol";
import "./ISequencerInbox.sol";
interface IInbox is IDelayedMessageProvider {
function bridge() external view returns (IBridge);
function sequencerInbox() external view returns (ISequencerInbox);
/**
* @notice Send a generic L2 message to the chain
* @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input
* This method will be disabled upon L1 fork to prevent replay attacks on L2
* @param messageData Data of the message being sent
*/
function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256);
/**
* @notice Send a generic L2 message to the chain
* @dev This method can be used to send any type of message that doesn't require L1 validation
* This method will be disabled upon L1 fork to prevent replay attacks on L2
* @param messageData Data of the message being sent
*/
function sendL2Message(bytes calldata messageData) external returns (uint256);
function sendL1FundedUnsignedTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
bytes calldata data
) external payable returns (uint256);
function sendL1FundedContractTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
address to,
bytes calldata data
) external payable returns (uint256);
function sendUnsignedTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
function sendContractTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
/**
* @dev This method can only be called upon L1 fork and will not alias the caller
* This method will revert if not called from origin
*/
function sendL1FundedUnsignedTransactionToFork(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
bytes calldata data
) external payable returns (uint256);
/**
* @dev This method can only be called upon L1 fork and will not alias the caller
* This method will revert if not called from origin
*/
function sendUnsignedTransactionToFork(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
/**
* @notice Send a message to initiate L2 withdrawal
* @dev This method can only be called upon L1 fork and will not alias the caller
* This method will revert if not called from origin
*/
function sendWithdrawEthToFork(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
uint256 value,
address withdrawTo
) external returns (uint256);
/**
* @notice Get the L1 fee for submitting a retryable
* @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
* @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
* @param dataLength The length of the retryable's calldata, in bytes
* @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
*/
function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
external
view
returns (uint256);
/**
* @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract
* @dev This does not trigger the fallback function when receiving in the L2 side.
* Look into retryable tickets if you are interested in this functionality.
* @dev This function should not be called inside contract constructors
*/
function depositEth() external payable returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev all msg.value will deposited to callValueRefundAddress on L2
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function createRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes calldata data
) external payable returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
* come from the deposit alone, rather than falling back on the user's L2 balance
* @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
* createRetryableTicket method is the recommended standard.
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function unsafeCreateRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes calldata data
) external payable returns (uint256);
// ---------- onlyRollupOrOwner functions ----------
/// @notice pauses all inbox functionality
function pause() external;
/// @notice unpauses all inbox functionality
function unpause() external;
// ---------- initializer ----------
/**
* @dev function to be called one time during the inbox upgrade process
* this is used to fix the storage slots
*/
function postUpgradeInit(IBridge _bridge) external;
function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
pragma experimental ABIEncoderV2;
import "../libraries/IGasRefunder.sol";
import "./IDelayedMessageProvider.sol";
import "./IBridge.sol";
interface ISequencerInbox is IDelayedMessageProvider {
struct MaxTimeVariation {
uint256 delayBlocks;
uint256 futureBlocks;
uint256 delaySeconds;
uint256 futureSeconds;
}
struct TimeBounds {
uint64 minTimestamp;
uint64 maxTimestamp;
uint64 minBlockNumber;
uint64 maxBlockNumber;
}
enum BatchDataLocation {
TxInput,
SeparateBatchEvent,
NoData
}
event SequencerBatchDelivered(
uint256 indexed batchSequenceNumber,
bytes32 indexed beforeAcc,
bytes32 indexed afterAcc,
bytes32 delayedAcc,
uint256 afterDelayedMessagesRead,
TimeBounds timeBounds,
BatchDataLocation dataLocation
);
event OwnerFunctionCalled(uint256 indexed id);
/// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input
event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data);
/// @dev a valid keyset was added
event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes);
/// @dev a keyset was invalidated
event InvalidateKeyset(bytes32 indexed keysetHash);
function totalDelayedMessagesRead() external view returns (uint256);
function bridge() external view returns (IBridge);
/// @dev The size of the batch header
// solhint-disable-next-line func-name-mixedcase
function HEADER_LENGTH() external view returns (uint256);
/// @dev If the first batch data byte after the header has this bit set,
/// the sequencer inbox has authenticated the data. Currently not used.
// solhint-disable-next-line func-name-mixedcase
function DATA_AUTHENTICATED_FLAG() external view returns (bytes1);
function rollup() external view returns (IOwnable);
function isBatchPoster(address) external view returns (bool);
struct DasKeySetInfo {
bool isValidKeyset;
uint64 creationBlock;
}
// https://github.com/ethereum/solidity/issues/11826
// function maxTimeVariation() external view returns (MaxTimeVariation calldata);
// function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata);
/// @notice Remove force inclusion delay after a L1 chainId fork
function removeDelayAfterFork() external;
/// @notice Force messages from the delayed inbox to be included in the chain
/// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and
/// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these
/// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages.
/// @param _totalDelayedMessagesRead The total number of messages to read up to
/// @param kind The kind of the last message to be included
/// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
/// @param baseFeeL1 The l1 gas price of the last message to be included
/// @param sender The sender of the last message to be included
/// @param messageDataHash The messageDataHash of the last message to be included
function forceInclusion(
uint256 _totalDelayedMessagesRead,
uint8 kind,
uint64[2] calldata l1BlockAndTime,
uint256 baseFeeL1,
address sender,
bytes32 messageDataHash
) external;
function inboxAccs(uint256 index) external view returns (bytes32);
function batchCount() external view returns (uint256);
function isValidKeysetHash(bytes32 ksHash) external view returns (bool);
/// @notice the creation block is intended to still be available after a keyset is deleted
function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256);
// ---------- BatchPoster functions ----------
function addSequencerL2BatchFromOrigin(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder
) external;
function addSequencerL2Batch(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder,
uint256 prevMessageCount,
uint256 newMessageCount
) external;
// ---------- onlyRollupOrOwner functions ----------
/**
* @notice Set max delay for sequencer inbox
* @param maxTimeVariation_ the maximum time variation parameters
*/
function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external;
/**
* @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox
* @param addr the address
* @param isBatchPoster_ if the specified address should be authorized as a batch poster
*/
function setIsBatchPoster(address addr, bool isBatchPoster_) external;
/**
* @notice Makes Data Availability Service keyset valid
* @param keysetBytes bytes of the serialized keyset
*/
function setValidKeyset(bytes calldata keysetBytes) external;
/**
* @notice Invalidates a Data Availability Service keyset
* @param ksHash hash of the keyset
*/
function invalidateKeysetHash(bytes32 ksHash) external;
// ---------- initializer ----------
function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./RollupLib.sol";
import "./IRollupCore.sol";
import "../bridge/ISequencerInbox.sol";
import "../bridge/IOutbox.sol";
import "../bridge/IOwnable.sol";
interface IRollupUserAbs is IRollupCore, IOwnable {
/// @dev the user logic just validated configuration and shouldn't write to state during init
/// this allows the admin logic to ensure consistency on parameters.
function initialize(address stakeToken) external view;
function removeWhitelistAfterFork() external;
function removeWhitelistAfterValidatorAfk() external;
function isERC20Enabled() external view returns (bool);
function rejectNextNode(address stakerAddress) external;
function confirmNextNode(bytes32 blockHash, bytes32 sendRoot) external;
function stakeOnExistingNode(uint64 nodeNum, bytes32 nodeHash) external;
function stakeOnNewNode(
RollupLib.Assertion memory assertion,
bytes32 expectedNodeHash,
uint256 prevNodeInboxMaxCount
) external;
function returnOldDeposit(address stakerAddress) external;
function reduceDeposit(uint256 target) external;
function removeZombie(uint256 zombieNum, uint256 maxNodes) external;
function removeOldZombies(uint256 startIndex) external;
function requiredStake(
uint256 blockNumber,
uint64 firstUnresolvedNodeNum,
uint64 latestCreatedNode
) external view returns (uint256);
function currentRequiredStake() external view returns (uint256);
function countStakedZombies(uint64 nodeNum) external view returns (uint256);
function countZombiesStakedOnChildren(uint64 nodeNum) external view returns (uint256);
function requireUnresolvedExists() external view;
function requireUnresolved(uint256 nodeNum) external view;
function withdrawStakerFunds() external returns (uint256);
function createChallenge(
address[2] calldata stakers,
uint64[2] calldata nodeNums,
MachineStatus[2] calldata machineStatuses,
GlobalState[2] calldata globalStates,
uint64 numBlocks,
bytes32 secondExecutionHash,
uint256[2] calldata proposedTimes,
bytes32[2] calldata wasmModuleRoots
) external;
}
interface IRollupUser is IRollupUserAbs {
function newStakeOnExistingNode(uint64 nodeNum, bytes32 nodeHash) external payable;
function newStakeOnNewNode(
RollupLib.Assertion calldata assertion,
bytes32 expectedNodeHash,
uint256 prevNodeInboxMaxCount
) external payable;
function addToDeposit(address stakerAddress) external payable;
}
interface IRollupUserERC20 is IRollupUserAbs {
function newStakeOnExistingNode(
uint256 tokenAmount,
uint64 nodeNum,
bytes32 nodeHash
) external;
function newStakeOnNewNode(
uint256 tokenAmount,
RollupLib.Assertion calldata assertion,
bytes32 expectedNodeHash,
uint256 prevNodeInboxMaxCount
) external;
function addToDeposit(address stakerAddress, uint256 tokenAmount) external;
}
interface IRollupAdmin {
event OwnerFunctionCalled(uint256 indexed id);
function initialize(Config calldata config, ContractDependencies calldata connectedContracts)
external;
/**
* @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 setDelayedInbox(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 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 proxy
* @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(uint64 newConfirmPeriod) external;
/**
* @notice Set number of extra blocks after a challenge
* @param newExtraTimeBlocks new number of blocks
*/
function setExtraChallengeTimeBlocks(uint64 newExtraTimeBlocks) 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 logic!
* @param newStakeToken address of token used for staking
*/
function setStakeToken(address newStakeToken) 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(
uint64 prevNode,
uint256 prevNodeInboxMaxCount,
RollupLib.Assertion memory assertion,
bytes32 expectedNodeHash
) external;
function forceConfirmNode(
uint64 nodeNum,
bytes32 blockHash,
bytes32 sendRoot
) external;
function setLoserStakeEscrow(address newLoserStakerEscrow) external;
/**
* @notice Set the proving WASM module root
* @param newWasmModuleRoot new module root
*/
function setWasmModuleRoot(bytes32 newWasmModuleRoot) external;
/**
* @notice set a new sequencer inbox contract
* @param _sequencerInbox new address of sequencer inbox
*/
function setSequencerInbox(address _sequencerInbox) external;
/**
* @notice set the validatorWhitelistDisabled flag
* @param _validatorWhitelistDisabled new value of validatorWhitelistDisabled, i.e. true = disabled
*/
function setValidatorWhitelistDisabled(bool _validatorWhitelistDisabled) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library Messages {
function messageHash(
uint8 kind,
address sender,
uint64 blockNumber,
uint64 timestamp,
uint256 inboxSeqNum,
uint256 baseFeeL1,
bytes32 messageDataHash
) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
kind,
sender,
blockNumber,
timestamp,
inboxSeqNum,
baseFeeL1,
messageDataHash
)
);
}
function accumulateInboxMessage(bytes32 prevAcc, bytes32 message)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(prevAcc, message));
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
uint8 constant L2_MSG = 3;
uint8 constant L1MessageType_L2FundedByL1 = 7;
uint8 constant L1MessageType_submitRetryableTx = 9;
uint8 constant L1MessageType_ethDeposit = 12;
uint8 constant L1MessageType_batchPostingReport = 13;
uint8 constant L2MessageType_unsignedEOATx = 0;
uint8 constant L2MessageType_unsignedContractTx = 1;
uint8 constant ROLLUP_PROTOCOL_EVENT_TYPE = 8;
uint8 constant INITIALIZATION_MSG_TYPE = 11;
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
interface IGasRefunder {
function onGasSpent(
address payable spender,
uint256 gasUsed,
uint256 calldataSize
) external returns (bool success);
}
abstract contract GasRefundEnabled {
/// @dev this refunds the sender for execution costs of the tx
/// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging
/// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded
modifier refundsGas(IGasRefunder gasRefunder) {
uint256 startGasLeft = gasleft();
_;
if (address(gasRefunder) != address(0)) {
uint256 calldataSize;
assembly {
calldataSize := calldatasize()
}
uint256 calldataWords = (calldataSize + 31) / 32;
// account for the CALLDATACOPY cost of the proxy contract, including the memory expansion cost
startGasLeft += calldataWords * 6 + (calldataWords**2) / 512;
// if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call
// so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input
// solhint-disable-next-line avoid-tx-origin
if (msg.sender != tx.origin) {
// We can't be sure if this calldata came from the top level tx,
// so to be safe we tell the gas refunder there was no calldata.
calldataSize = 0;
}
gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize);
}
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {NotOwner} from "./Error.sol";
/// @dev A stateless contract that allows you to infer if the current call has been delegated or not
/// Pattern used here is from UUPS implementation by the OpenZeppelin team
abstract contract DelegateCallAware {
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegate call. This allows a function to be
* callable on the proxy contract but not on the logic contract.
*/
modifier onlyDelegated() {
require(address(this) != __self, "Function must be called through delegatecall");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "Function must not be called through delegatecall");
_;
}
/// @dev Check that msg.sender is the current EIP 1967 proxy admin
modifier onlyProxyOwner() {
// Storage slot with the admin of the proxy contract
// This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1
bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
address admin;
assembly {
admin := sload(slot)
}
if (msg.sender != admin) revert NotOwner(msg.sender, admin);
_;
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
// 90% of Geth's 128KB tx size limit, leaving ~13KB for proving
uint256 constant MAX_DATA_SIZE = 117964;
uint64 constant NO_CHAL_INDEX = 0;
// Expected seconds per block in Ethereum PoS
uint256 constant ETH_POS_BLOCK_TIME = 12;
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.4.21 <0.9.0;
interface IOwnable {
function owner() external view returns (address);
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
interface IDelayedMessageProvider {
/// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
event InboxMessageDelivered(uint256 indexed messageNum, bytes data);
/// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
/// same as InboxMessageDelivered but the batch data is available in tx.input
event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../challenge/IChallengeManager.sol";
import "../challenge/ChallengeLib.sol";
import "../state/GlobalState.sol";
import "../bridge/ISequencerInbox.sol";
import "../bridge/IBridge.sol";
import "../bridge/IOutbox.sol";
import "../bridge/IInbox.sol";
import "./IRollupEventInbox.sol";
import "./IRollupLogic.sol";
struct Config {
uint64 confirmPeriodBlocks;
uint64 extraChallengeTimeBlocks;
address stakeToken;
uint256 baseStake;
bytes32 wasmModuleRoot;
address owner;
address loserStakeEscrow;
uint256 chainId;
uint64 genesisBlockNum;
ISequencerInbox.MaxTimeVariation sequencerInboxMaxTimeVariation;
}
struct ContractDependencies {
IBridge bridge;
ISequencerInbox sequencerInbox;
IInbox inbox;
IOutbox outbox;
IRollupEventInbox rollupEventInbox;
IChallengeManager challengeManager;
IRollupAdmin rollupAdminLogic;
IRollupUser rollupUserLogic;
// misc contracts that are useful when interacting with the rollup
address validatorUtils;
address validatorWalletCreator;
}
library RollupLib {
using GlobalStateLib for GlobalState;
struct ExecutionState {
GlobalState globalState;
MachineStatus machineStatus;
}
function stateHash(ExecutionState calldata execState, uint256 inboxMaxCount)
internal
pure
returns (bytes32)
{
return
keccak256(
abi.encodePacked(
execState.globalState.hash(),
inboxMaxCount,
execState.machineStatus
)
);
}
/// @dev same as stateHash but expects execState in memory instead of calldata
function stateHashMem(ExecutionState memory execState, uint256 inboxMaxCount)
internal
pure
returns (bytes32)
{
return
keccak256(
abi.encodePacked(
execState.globalState.hash(),
inboxMaxCount,
execState.machineStatus
)
);
}
struct Assertion {
ExecutionState beforeState;
ExecutionState afterState;
uint64 numBlocks;
}
function executionHash(Assertion memory assertion) internal pure returns (bytes32) {
MachineStatus[2] memory statuses;
statuses[0] = assertion.beforeState.machineStatus;
statuses[1] = assertion.afterState.machineStatus;
GlobalState[2] memory globalStates;
globalStates[0] = assertion.beforeState.globalState;
globalStates[1] = assertion.afterState.globalState;
// TODO: benchmark how much this abstraction adds of gas overhead
return executionHash(statuses, globalStates, assertion.numBlocks);
}
function executionHash(
MachineStatus[2] memory statuses,
GlobalState[2] memory globalStates,
uint64 numBlocks
) internal pure returns (bytes32) {
bytes32[] memory segments = new bytes32[](2);
segments[0] = ChallengeLib.blockStateHash(statuses[0], globalStates[0].hash());
segments[1] = ChallengeLib.blockStateHash(statuses[1], globalStates[1].hash());
return ChallengeLib.hashChallengeState(0, numBlocks, segments);
}
function challengeRootHash(
bytes32 execution,
uint256 proposedTime,
bytes32 wasmModuleRoot
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(execution, proposedTime, wasmModuleRoot));
}
function confirmHash(Assertion memory assertion) internal pure returns (bytes32) {
return
confirmHash(
assertion.afterState.globalState.getBlockHash(),
assertion.afterState.globalState.getSendRoot()
);
}
function confirmHash(bytes32 blockHash, bytes32 sendRoot) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(blockHash, sendRoot));
}
function nodeHash(
bool hasSibling,
bytes32 lastHash,
bytes32 assertionExecHash,
bytes32 inboxAcc,
bytes32 wasmModuleRoot
) internal pure returns (bytes32) {
uint8 hasSiblingInt = hasSibling ? 1 : 0;
return
keccak256(
abi.encodePacked(
hasSiblingInt,
lastHash,
assertionExecHash,
inboxAcc,
wasmModuleRoot
)
);
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./Node.sol";
import "./RollupLib.sol";
interface IRollupCore {
struct Staker {
uint256 amountStaked;
uint64 index;
uint64 latestStakedNode;
// currentChallenge is 0 if staker is not in a challenge
uint64 currentChallenge;
bool isStaked;
}
event RollupInitialized(bytes32 machineHash, uint256 chainId);
event NodeCreated(
uint64 indexed nodeNum,
bytes32 indexed parentNodeHash,
bytes32 indexed nodeHash,
bytes32 executionHash,
RollupLib.Assertion assertion,
bytes32 afterInboxBatchAcc,
bytes32 wasmModuleRoot,
uint256 inboxMaxCount
);
event NodeConfirmed(uint64 indexed nodeNum, bytes32 blockHash, bytes32 sendRoot);
event NodeRejected(uint64 indexed nodeNum);
event RollupChallengeStarted(
uint64 indexed challengeIndex,
address asserter,
address challenger,
uint64 challengedNode
);
event UserStakeUpdated(address indexed user, uint256 initialBalance, uint256 finalBalance);
event UserWithdrawableFundsUpdated(
address indexed user,
uint256 initialBalance,
uint256 finalBalance
);
function confirmPeriodBlocks() external view returns (uint64);
function extraChallengeTimeBlocks() external view returns (uint64);
function chainId() external view returns (uint256);
function baseStake() external view returns (uint256);
function wasmModuleRoot() external view returns (bytes32);
function bridge() external view returns (IBridge);
function sequencerInbox() external view returns (ISequencerInbox);
function outbox() external view returns (IOutbox);
function rollupEventInbox() external view returns (IRollupEventInbox);
function challengeManager() external view returns (IChallengeManager);
function loserStakeEscrow() external view returns (address);
function stakeToken() external view returns (address);
function minimumAssertionPeriod() external view returns (uint256);
function isValidator(address) external view returns (bool);
function validatorWhitelistDisabled() external view returns (bool);
/**
* @notice Get the Node for the given index.
*/
function getNode(uint64 nodeNum) external view returns (Node memory);
/**
* @notice Check if the specified node has been staked on by the provided staker.
* Only accurate at the latest confirmed node and afterwards.
*/
function nodeHasStaker(uint64 nodeNum, address staker) external view returns (bool);
/**
* @notice Get the address of the staker at the given index
* @param stakerNum Index of the staker
* @return Address of the staker
*/
function getStakerAddress(uint64 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 (uint64);
/**
* @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 (uint64);
/**
* @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 Retrieves stored information about a requested staker
* @param staker Staker address to retrieve
* @return A structure with information about the requested staker
*/
function getStaker(address staker) external view returns (Staker memory);
/**
* @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 (uint64);
/// @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 (uint64);
/// @return Index of the latest confirmed node
function latestConfirmed() external view returns (uint64);
/// @return Index of the latest rollup node created
function latestNodeCreated() external view returns (uint64);
/// @return Ethereum block that the most recent stake was created
function lastStakeBlock() external view returns (uint64);
/// @return Number of active stakers currently staked
function stakerCount() external view returns (uint64);
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IBridge.sol";
interface IOutbox {
event SendRootUpdated(bytes32 indexed outputRoot, bytes32 indexed l2BlockHash);
event OutBoxTransactionExecuted(
address indexed to,
address indexed l2Sender,
uint256 indexed zero,
uint256 transactionIndex
);
function rollup() external view returns (address); // the rollup contract
function bridge() external view returns (IBridge); // the bridge contract
function spent(uint256) external view returns (bytes32); // packed spent bitmap
function roots(bytes32) external view returns (bytes32); // maps root hashes => L2 block hash
// solhint-disable-next-line func-name-mixedcase
function OUTBOX_VERSION() external view returns (uint128); // the outbox version
function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;
/// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
/// When the return value is zero, that means this is a system message
/// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
function l2ToL1Sender() external view returns (address);
/// @return l2Block return L2 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
function l2ToL1Block() external view returns (uint256);
/// @return l1Block return L1 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
function l2ToL1EthBlock() external view returns (uint256);
/// @return timestamp return L2 timestamp when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
function l2ToL1Timestamp() external view returns (uint256);
/// @return outputId returns the unique output identifier of the L2 to L1 tx or 0 if no L2 to L1 transaction is active
function l2ToL1OutputId() external view returns (bytes32);
/**
* @notice Executes a messages in an Outbox entry.
* @dev Reverts if dispute period hasn't expired, since the outbox entry
* is only created once the rollup confirms the respective assertion.
* @dev it is not possible to execute any L2-to-L1 transaction which contains data
* to a contract address without any code (as enforced by the Bridge contract).
* @param proof Merkle proof of message inclusion in send root
* @param index Merkle path to message
* @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
* @param to destination address for L1 contract call
* @param l2Block l2 block number at which sendTxToL1 call was made
* @param l1Block l1 block number at which sendTxToL1 call was made
* @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
* @param value wei in L1 message
* @param data abi-encoded L1 message data
*/
function executeTransaction(
bytes32[] calldata proof,
uint256 index,
address l2Sender,
address to,
uint256 l2Block,
uint256 l1Block,
uint256 l2Timestamp,
uint256 value,
bytes calldata data
) external;
/**
* @dev function used to simulate the result of a particular function call from the outbox
* it is useful for things such as gas estimates. This function includes all costs except for
* proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
* not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
* We can't include the cost of proof validation since this is intended to be used to simulate txs
* that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
* to confirm a pending merkle root, but that would be less practical for integrating with tooling.
* It is only possible to trigger it when the msg sender is address zero, which should be impossible
* unless under simulation in an eth_call or eth_estimateGas
*/
function executeTransactionSimulation(
uint256 index,
address l2Sender,
address to,
uint256 l2Block,
uint256 l1Block,
uint256 l2Timestamp,
uint256 value,
bytes calldata data
) external;
/**
* @param index Merkle path to message
* @return true if the message has been spent
*/
function isSpent(uint256 index) external view returns (bool);
function calculateItemHash(
address l2Sender,
address to,
uint256 l2Block,
uint256 l1Block,
uint256 l2Timestamp,
uint256 value,
bytes calldata data
) external pure returns (bytes32);
function calculateMerkleRoot(
bytes32[] memory proof,
uint256 path,
bytes32 item
) external pure returns (bytes32);
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../state/Machine.sol";
import "../bridge/IBridge.sol";
import "../bridge/ISequencerInbox.sol";
import "../osp/IOneStepProofEntry.sol";
import "./IChallengeResultReceiver.sol";
import "./ChallengeLib.sol";
interface IChallengeManager {
enum ChallengeTerminationType {
TIMEOUT,
BLOCK_PROOF,
EXECUTION_PROOF,
CLEARED
}
event InitiatedChallenge(
uint64 indexed challengeIndex,
GlobalState startState,
GlobalState endState
);
event Bisected(
uint64 indexed challengeIndex,
bytes32 indexed challengeRoot,
uint256 challengedSegmentStart,
uint256 challengedSegmentLength,
bytes32[] chainHashes
);
event ExecutionChallengeBegun(uint64 indexed challengeIndex, uint256 blockSteps);
event OneStepProofCompleted(uint64 indexed challengeIndex);
event ChallengeEnded(uint64 indexed challengeIndex, ChallengeTerminationType kind);
function initialize(
IChallengeResultReceiver resultReceiver_,
ISequencerInbox sequencerInbox_,
IBridge bridge_,
IOneStepProofEntry osp_
) external;
function createChallenge(
bytes32 wasmModuleRoot_,
MachineStatus[2] calldata startAndEndMachineStatuses_,
GlobalState[2] calldata startAndEndGlobalStates_,
uint64 numBlocks,
address asserter_,
address challenger_,
uint256 asserterTimeLeft_,
uint256 challengerTimeLeft_
) external returns (uint64);
function challengeInfo(uint64 challengeIndex_)
external
view
returns (ChallengeLib.Challenge memory);
function currentResponder(uint64 challengeIndex) external view returns (address);
function isTimedOut(uint64 challengeIndex) external view returns (bool);
function clearChallenge(uint64 challengeIndex_) external;
function timeout(uint64 challengeIndex_) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../state/Machine.sol";
import "../state/GlobalState.sol";
library ChallengeLib {
using MachineLib for Machine;
using ChallengeLib for Challenge;
/// @dev It's assumed that that uninitialzed challenges have mode NONE
enum ChallengeMode {
NONE,
BLOCK,
EXECUTION
}
struct Participant {
address addr;
uint256 timeLeft;
}
struct Challenge {
Participant current;
Participant next;
uint256 lastMoveTimestamp;
bytes32 wasmModuleRoot;
bytes32 challengeStateHash;
uint64 maxInboxMessages;
ChallengeMode mode;
}
struct SegmentSelection {
uint256 oldSegmentsStart;
uint256 oldSegmentsLength;
bytes32[] oldSegments;
uint256 challengePosition;
}
function timeUsedSinceLastMove(Challenge storage challenge) internal view returns (uint256) {
return block.timestamp - challenge.lastMoveTimestamp;
}
function isTimedOut(Challenge storage challenge) internal view returns (bool) {
return challenge.timeUsedSinceLastMove() > challenge.current.timeLeft;
}
function getStartMachineHash(bytes32 globalStateHash, bytes32 wasmModuleRoot)
internal
pure
returns (bytes32)
{
// Start the value stack with the function call ABI for the entrypoint
Value[] memory startingValues = new Value[](3);
startingValues[0] = ValueLib.newRefNull();
startingValues[1] = ValueLib.newI32(0);
startingValues[2] = ValueLib.newI32(0);
ValueArray memory valuesArray = ValueArray({inner: startingValues});
ValueStack memory values = ValueStack({proved: valuesArray, remainingHash: 0});
ValueStack memory internalStack;
StackFrameWindow memory frameStack;
Machine memory mach = Machine({
status: MachineStatus.RUNNING,
valueStack: values,
internalStack: internalStack,
frameStack: frameStack,
globalStateHash: globalStateHash,
moduleIdx: 0,
functionIdx: 0,
functionPc: 0,
modulesRoot: wasmModuleRoot
});
return mach.hash();
}
function getEndMachineHash(MachineStatus status, bytes32 globalStateHash)
internal
pure
returns (bytes32)
{
if (status == MachineStatus.FINISHED) {
return keccak256(abi.encodePacked("Machine finished:", globalStateHash));
} else if (status == MachineStatus.ERRORED) {
return keccak256(abi.encodePacked("Machine errored:"));
} else if (status == MachineStatus.TOO_FAR) {
return keccak256(abi.encodePacked("Machine too far:"));
} else {
revert("BAD_BLOCK_STATUS");
}
}
function extractChallengeSegment(SegmentSelection calldata selection)
internal
pure
returns (uint256 segmentStart, uint256 segmentLength)
{
uint256 oldChallengeDegree = selection.oldSegments.length - 1;
segmentLength = selection.oldSegmentsLength / oldChallengeDegree;
// Intentionally done before challengeLength is potentially added to for the final segment
segmentStart = selection.oldSegmentsStart + segmentLength * selection.challengePosition;
if (selection.challengePosition == selection.oldSegments.length - 2) {
segmentLength += selection.oldSegmentsLength % oldChallengeDegree;
}
}
function hashChallengeState(
uint256 segmentsStart,
uint256 segmentsLength,
bytes32[] memory segments
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(segmentsStart, segmentsLength, segments));
}
function blockStateHash(MachineStatus status, bytes32 globalStateHash)
internal
pure
returns (bytes32)
{
if (status == MachineStatus.FINISHED) {
return keccak256(abi.encodePacked("Block state:", globalStateHash));
} else if (status == MachineStatus.ERRORED) {
return keccak256(abi.encodePacked("Block state, errored:", globalStateHash));
} else if (status == MachineStatus.TOO_FAR) {
return keccak256(abi.encodePacked("Block state, too far:"));
} else {
revert("BAD_BLOCK_STATUS");
}
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
struct GlobalState {
bytes32[2] bytes32Vals;
uint64[2] u64Vals;
}
library GlobalStateLib {
uint16 internal constant BYTES32_VALS_NUM = 2;
uint16 internal constant U64_VALS_NUM = 2;
function hash(GlobalState memory state) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
"Global state:",
state.bytes32Vals[0],
state.bytes32Vals[1],
state.u64Vals[0],
state.u64Vals[1]
)
);
}
function getBlockHash(GlobalState memory state) internal pure returns (bytes32) {
return state.bytes32Vals[0];
}
function getSendRoot(GlobalState memory state) internal pure returns (bytes32) {
return state.bytes32Vals[1];
}
function getInboxPosition(GlobalState memory state) internal pure returns (uint64) {
return state.u64Vals[0];
}
function getPositionInMessage(GlobalState memory state) internal pure returns (uint64) {
return state.u64Vals[1];
}
function isEmpty(GlobalState calldata state) internal pure returns (bool) {
return (state.bytes32Vals[0] == bytes32(0) &&
state.bytes32Vals[1] == bytes32(0) &&
state.u64Vals[0] == 0 &&
state.u64Vals[1] == 0);
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../bridge/IBridge.sol";
interface IRollupEventInbox {
function bridge() external view returns (IBridge);
function initialize(IBridge _bridge) external;
function rollup() external view returns (address);
function rollupInitialized(uint256 chainId) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./ValueStack.sol";
import "./Instructions.sol";
import "./StackFrame.sol";
enum MachineStatus {
RUNNING,
FINISHED,
ERRORED,
TOO_FAR
}
struct Machine {
MachineStatus status;
ValueStack valueStack;
ValueStack internalStack;
StackFrameWindow frameStack;
bytes32 globalStateHash;
uint32 moduleIdx;
uint32 functionIdx;
uint32 functionPc;
bytes32 modulesRoot;
}
library MachineLib {
using StackFrameLib for StackFrameWindow;
using ValueStackLib for ValueStack;
function hash(Machine memory mach) internal pure returns (bytes32) {
// Warning: the non-running hashes are replicated in Challenge
if (mach.status == MachineStatus.RUNNING) {
return
keccak256(
abi.encodePacked(
"Machine running:",
mach.valueStack.hash(),
mach.internalStack.hash(),
mach.frameStack.hash(),
mach.globalStateHash,
mach.moduleIdx,
mach.functionIdx,
mach.functionPc,
mach.modulesRoot
)
);
} else if (mach.status == MachineStatus.FINISHED) {
return keccak256(abi.encodePacked("Machine finished:", mach.globalStateHash));
} else if (mach.status == MachineStatus.ERRORED) {
return keccak256(abi.encodePacked("Machine errored:"));
} else if (mach.status == MachineStatus.TOO_FAR) {
return keccak256(abi.encodePacked("Machine too far:"));
} else {
revert("BAD_MACH_STATUS");
}
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./IOneStepProver.sol";
library OneStepProofEntryLib {
uint256 internal constant MAX_STEPS = 1 << 43;
}
interface IOneStepProofEntry {
function proveOneStep(
ExecutionContext calldata execCtx,
uint256 machineStep,
bytes32 beforeHash,
bytes calldata proof
) external view returns (bytes32 afterHash);
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IChallengeResultReceiver {
function completeChallenge(
uint256 challengeIndex,
address winner,
address loser
) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./Value.sol";
import "./ValueArray.sol";
struct ValueStack {
ValueArray proved;
bytes32 remainingHash;
}
library ValueStackLib {
using ValueLib for Value;
using ValueArrayLib for ValueArray;
function hash(ValueStack memory stack) internal pure returns (bytes32 h) {
h = stack.remainingHash;
uint256 len = stack.proved.length();
for (uint256 i = 0; i < len; i++) {
h = keccak256(abi.encodePacked("Value stack:", stack.proved.get(i).hash(), h));
}
}
function peek(ValueStack memory stack) internal pure returns (Value memory) {
uint256 len = stack.proved.length();
return stack.proved.get(len - 1);
}
function pop(ValueStack memory stack) internal pure returns (Value memory) {
return stack.proved.pop();
}
function push(ValueStack memory stack, Value memory val) internal pure {
return stack.proved.push(val);
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
struct Instruction {
uint16 opcode;
uint256 argumentData;
}
library Instructions {
uint16 internal constant UNREACHABLE = 0x00;
uint16 internal constant NOP = 0x01;
uint16 internal constant RETURN = 0x0F;
uint16 internal constant CALL = 0x10;
uint16 internal constant CALL_INDIRECT = 0x11;
uint16 internal constant LOCAL_GET = 0x20;
uint16 internal constant LOCAL_SET = 0x21;
uint16 internal constant GLOBAL_GET = 0x23;
uint16 internal constant GLOBAL_SET = 0x24;
uint16 internal constant I32_LOAD = 0x28;
uint16 internal constant I64_LOAD = 0x29;
uint16 internal constant F32_LOAD = 0x2A;
uint16 internal constant F64_LOAD = 0x2B;
uint16 internal constant I32_LOAD8_S = 0x2C;
uint16 internal constant I32_LOAD8_U = 0x2D;
uint16 internal constant I32_LOAD16_S = 0x2E;
uint16 internal constant I32_LOAD16_U = 0x2F;
uint16 internal constant I64_LOAD8_S = 0x30;
uint16 internal constant I64_LOAD8_U = 0x31;
uint16 internal constant I64_LOAD16_S = 0x32;
uint16 internal constant I64_LOAD16_U = 0x33;
uint16 internal constant I64_LOAD32_S = 0x34;
uint16 internal constant I64_LOAD32_U = 0x35;
uint16 internal constant I32_STORE = 0x36;
uint16 internal constant I64_STORE = 0x37;
uint16 internal constant F32_STORE = 0x38;
uint16 internal constant F64_STORE = 0x39;
uint16 internal constant I32_STORE8 = 0x3A;
uint16 internal constant I32_STORE16 = 0x3B;
uint16 internal constant I64_STORE8 = 0x3C;
uint16 internal constant I64_STORE16 = 0x3D;
uint16 internal constant I64_STORE32 = 0x3E;
uint16 internal constant MEMORY_SIZE = 0x3F;
uint16 internal constant MEMORY_GROW = 0x40;
uint16 internal constant DROP = 0x1A;
uint16 internal constant SELECT = 0x1B;
uint16 internal constant I32_CONST = 0x41;
uint16 internal constant I64_CONST = 0x42;
uint16 internal constant F32_CONST = 0x43;
uint16 internal constant F64_CONST = 0x44;
uint16 internal constant I32_EQZ = 0x45;
uint16 internal constant I32_RELOP_BASE = 0x46;
uint16 internal constant IRELOP_EQ = 0;
uint16 internal constant IRELOP_NE = 1;
uint16 internal constant IRELOP_LT_S = 2;
uint16 internal constant IRELOP_LT_U = 3;
uint16 internal constant IRELOP_GT_S = 4;
uint16 internal constant IRELOP_GT_U = 5;
uint16 internal constant IRELOP_LE_S = 6;
uint16 internal constant IRELOP_LE_U = 7;
uint16 internal constant IRELOP_GE_S = 8;
uint16 internal constant IRELOP_GE_U = 9;
uint16 internal constant IRELOP_LAST = IRELOP_GE_U;
uint16 internal constant I64_EQZ = 0x50;
uint16 internal constant I64_RELOP_BASE = 0x51;
uint16 internal constant I32_UNOP_BASE = 0x67;
uint16 internal constant IUNOP_CLZ = 0;
uint16 internal constant IUNOP_CTZ = 1;
uint16 internal constant IUNOP_POPCNT = 2;
uint16 internal constant IUNOP_LAST = IUNOP_POPCNT;
uint16 internal constant I32_ADD = 0x6A;
uint16 internal constant I32_SUB = 0x6B;
uint16 internal constant I32_MUL = 0x6C;
uint16 internal constant I32_DIV_S = 0x6D;
uint16 internal constant I32_DIV_U = 0x6E;
uint16 internal constant I32_REM_S = 0x6F;
uint16 internal constant I32_REM_U = 0x70;
uint16 internal constant I32_AND = 0x71;
uint16 internal constant I32_OR = 0x72;
uint16 internal constant I32_XOR = 0x73;
uint16 internal constant I32_SHL = 0x74;
uint16 internal constant I32_SHR_S = 0x75;
uint16 internal constant I32_SHR_U = 0x76;
uint16 internal constant I32_ROTL = 0x77;
uint16 internal constant I32_ROTR = 0x78;
uint16 internal constant I64_UNOP_BASE = 0x79;
uint16 internal constant I64_ADD = 0x7C;
uint16 internal constant I64_SUB = 0x7D;
uint16 internal constant I64_MUL = 0x7E;
uint16 internal constant I64_DIV_S = 0x7F;
uint16 internal constant I64_DIV_U = 0x80;
uint16 internal constant I64_REM_S = 0x81;
uint16 internal constant I64_REM_U = 0x82;
uint16 internal constant I64_AND = 0x83;
uint16 internal constant I64_OR = 0x84;
uint16 internal constant I64_XOR = 0x85;
uint16 internal constant I64_SHL = 0x86;
uint16 internal constant I64_SHR_S = 0x87;
uint16 internal constant I64_SHR_U = 0x88;
uint16 internal constant I64_ROTL = 0x89;
uint16 internal constant I64_ROTR = 0x8A;
uint16 internal constant I32_WRAP_I64 = 0xA7;
uint16 internal constant I64_EXTEND_I32_S = 0xAC;
uint16 internal constant I64_EXTEND_I32_U = 0xAD;
uint16 internal constant I32_REINTERPRET_F32 = 0xBC;
uint16 internal constant I64_REINTERPRET_F64 = 0xBD;
uint16 internal constant F32_REINTERPRET_I32 = 0xBE;
uint16 internal constant F64_REINTERPRET_I64 = 0xBF;
uint16 internal constant I32_EXTEND_8S = 0xC0;
uint16 internal constant I32_EXTEND_16S = 0xC1;
uint16 internal constant I64_EXTEND_8S = 0xC2;
uint16 internal constant I64_EXTEND_16S = 0xC3;
uint16 internal constant I64_EXTEND_32S = 0xC4;
uint16 internal constant INIT_FRAME = 0x8002;
uint16 internal constant ARBITRARY_JUMP = 0x8003;
uint16 internal constant ARBITRARY_JUMP_IF = 0x8004;
uint16 internal constant MOVE_FROM_STACK_TO_INTERNAL = 0x8005;
uint16 internal constant MOVE_FROM_INTERNAL_TO_STACK = 0x8006;
uint16 internal constant DUP = 0x8008;
uint16 internal constant CROSS_MODULE_CALL = 0x8009;
uint16 internal constant CALLER_MODULE_INTERNAL_CALL = 0x800A;
uint16 internal constant GET_GLOBAL_STATE_BYTES32 = 0x8010;
uint16 internal constant SET_GLOBAL_STATE_BYTES32 = 0x8011;
uint16 internal constant GET_GLOBAL_STATE_U64 = 0x8012;
uint16 internal constant SET_GLOBAL_STATE_U64 = 0x8013;
uint16 internal constant READ_PRE_IMAGE = 0x8020;
uint16 internal constant READ_INBOX_MESSAGE = 0x8021;
uint16 internal constant HALT_AND_SET_FINISHED = 0x8022;
uint256 internal constant INBOX_INDEX_SEQUENCER = 0;
uint256 internal constant INBOX_INDEX_DELAYED = 1;
function hash(Instruction memory inst) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("Instruction:", inst.opcode, inst.argumentData));
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./Value.sol";
struct StackFrame {
Value returnPc;
bytes32 localsMerkleRoot;
uint32 callerModule;
uint32 callerModuleInternals;
}
struct StackFrameWindow {
StackFrame[] proved;
bytes32 remainingHash;
}
library StackFrameLib {
using ValueLib for Value;
function hash(StackFrame memory frame) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
"Stack frame:",
frame.returnPc.hash(),
frame.localsMerkleRoot,
frame.callerModule,
frame.callerModuleInternals
)
);
}
function hash(StackFrameWindow memory window) internal pure returns (bytes32 h) {
h = window.remainingHash;
for (uint256 i = 0; i < window.proved.length; i++) {
h = keccak256(abi.encodePacked("Stack frame stack:", hash(window.proved[i]), h));
}
}
function peek(StackFrameWindow memory window) internal pure returns (StackFrame memory) {
require(window.proved.length == 1, "BAD_WINDOW_LENGTH");
return window.proved[0];
}
function pop(StackFrameWindow memory window) internal pure returns (StackFrame memory frame) {
require(window.proved.length == 1, "BAD_WINDOW_LENGTH");
frame = window.proved[0];
window.proved = new StackFrame[](0);
}
function push(StackFrameWindow memory window, StackFrame memory frame) internal pure {
StackFrame[] memory newProved = new StackFrame[](window.proved.length + 1);
for (uint256 i = 0; i < window.proved.length; i++) {
newProved[i] = window.proved[i];
}
newProved[window.proved.length] = frame;
window.proved = newProved;
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
enum ValueType {
I32,
I64,
F32,
F64,
REF_NULL,
FUNC_REF,
INTERNAL_REF
}
struct Value {
ValueType valueType;
uint256 contents;
}
library ValueLib {
function hash(Value memory val) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("Value:", val.valueType, val.contents));
}
function maxValueType() internal pure returns (ValueType) {
return ValueType.INTERNAL_REF;
}
function assumeI32(Value memory val) internal pure returns (uint32) {
uint256 uintval = uint256(val.contents);
require(val.valueType == ValueType.I32, "NOT_I32");
require(uintval < (1 << 32), "BAD_I32");
return uint32(uintval);
}
function assumeI64(Value memory val) internal pure returns (uint64) {
uint256 uintval = uint256(val.contents);
require(val.valueType == ValueType.I64, "NOT_I64");
require(uintval < (1 << 64), "BAD_I64");
return uint64(uintval);
}
function newRefNull() internal pure returns (Value memory) {
return Value({valueType: ValueType.REF_NULL, contents: 0});
}
function newI32(uint32 x) internal pure returns (Value memory) {
return Value({valueType: ValueType.I32, contents: uint256(x)});
}
function newI64(uint64 x) internal pure returns (Value memory) {
return Value({valueType: ValueType.I64, contents: uint256(x)});
}
function newBoolean(bool x) internal pure returns (Value memory) {
if (x) {
return newI32(uint32(1));
} else {
return newI32(uint32(0));
}
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./Value.sol";
struct ValueArray {
Value[] inner;
}
library ValueArrayLib {
function get(ValueArray memory arr, uint256 index) internal pure returns (Value memory) {
return arr.inner[index];
}
function set(
ValueArray memory arr,
uint256 index,
Value memory val
) internal pure {
arr.inner[index] = val;
}
function length(ValueArray memory arr) internal pure returns (uint256) {
return arr.inner.length;
}
function push(ValueArray memory arr, Value memory val) internal pure {
Value[] memory newInner = new Value[](arr.inner.length + 1);
for (uint256 i = 0; i < arr.inner.length; i++) {
newInner[i] = arr.inner[i];
}
newInner[arr.inner.length] = val;
arr.inner = newInner;
}
function pop(ValueArray memory arr) internal pure returns (Value memory popped) {
popped = arr.inner[arr.inner.length - 1];
Value[] memory newInner = new Value[](arr.inner.length - 1);
for (uint256 i = 0; i < newInner.length; i++) {
newInner[i] = arr.inner[i];
}
arr.inner = newInner;
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../state/Machine.sol";
import "../state/Module.sol";
import "../state/Instructions.sol";
import "../bridge/ISequencerInbox.sol";
import "../bridge/IBridge.sol";
struct ExecutionContext {
uint256 maxInboxMessagesRead;
IBridge bridge;
}
abstract contract IOneStepProver {
function executeOneStep(
ExecutionContext memory execCtx,
Machine calldata mach,
Module calldata mod,
Instruction calldata instruction,
bytes calldata proof
) external view virtual returns (Machine memory result, Module memory resultMod);
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./ModuleMemory.sol";
struct Module {
bytes32 globalsMerkleRoot;
ModuleMemory moduleMemory;
bytes32 tablesMerkleRoot;
bytes32 functionsMerkleRoot;
uint32 internalsOffset;
}
library ModuleLib {
using ModuleMemoryLib for ModuleMemory;
function hash(Module memory mod) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
"Module:",
mod.globalsMerkleRoot,
mod.moduleMemory.hash(),
mod.tablesMerkleRoot,
mod.functionsMerkleRoot,
mod.internalsOffset
)
);
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./MerkleProof.sol";
import "./Deserialize.sol";
struct ModuleMemory {
uint64 size;
uint64 maxSize;
bytes32 merkleRoot;
}
library ModuleMemoryLib {
using MerkleProofLib for MerkleProof;
function hash(ModuleMemory memory mem) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("Memory:", mem.size, mem.maxSize, mem.merkleRoot));
}
function proveLeaf(
ModuleMemory memory mem,
uint256 leafIdx,
bytes calldata proof,
uint256 startOffset
)
internal
pure
returns (
bytes32 contents,
uint256 offset,
MerkleProof memory merkle
)
{
offset = startOffset;
(contents, offset) = Deserialize.b32(proof, offset);
(merkle, offset) = Deserialize.merkleProof(proof, offset);
bytes32 recomputedRoot = merkle.computeRootFromMemory(leafIdx, contents);
require(recomputedRoot == mem.merkleRoot, "WRONG_MEM_ROOT");
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./Value.sol";
import "./Instructions.sol";
import "./Module.sol";
struct MerkleProof {
bytes32[] counterparts;
}
library MerkleProofLib {
using ModuleLib for Module;
using ValueLib for Value;
function computeRootFromValue(
MerkleProof memory proof,
uint256 index,
Value memory leaf
) internal pure returns (bytes32) {
return computeRootUnsafe(proof, index, leaf.hash(), "Value merkle tree:");
}
function computeRootFromInstruction(
MerkleProof memory proof,
uint256 index,
Instruction memory inst
) internal pure returns (bytes32) {
return computeRootUnsafe(proof, index, Instructions.hash(inst), "Instruction merkle tree:");
}
function computeRootFromFunction(
MerkleProof memory proof,
uint256 index,
bytes32 codeRoot
) internal pure returns (bytes32) {
bytes32 h = keccak256(abi.encodePacked("Function:", codeRoot));
return computeRootUnsafe(proof, index, h, "Function merkle tree:");
}
function computeRootFromMemory(
MerkleProof memory proof,
uint256 index,
bytes32 contents
) internal pure returns (bytes32) {
bytes32 h = keccak256(abi.encodePacked("Memory leaf:", contents));
return computeRootUnsafe(proof, index, h, "Memory merkle tree:");
}
function computeRootFromElement(
MerkleProof memory proof,
uint256 index,
bytes32 funcTypeHash,
Value memory val
) internal pure returns (bytes32) {
bytes32 h = keccak256(abi.encodePacked("Table element:", funcTypeHash, val.hash()));
return computeRootUnsafe(proof, index, h, "Table element merkle tree:");
}
function computeRootFromTable(
MerkleProof memory proof,
uint256 index,
uint8 tableType,
uint64 tableSize,
bytes32 elementsRoot
) internal pure returns (bytes32) {
bytes32 h = keccak256(abi.encodePacked("Table:", tableType, tableSize, elementsRoot));
return computeRootUnsafe(proof, index, h, "Table merkle tree:");
}
function computeRootFromModule(
MerkleProof memory proof,
uint256 index,
Module memory mod
) internal pure returns (bytes32) {
return computeRootUnsafe(proof, index, mod.hash(), "Module merkle tree:");
}
// WARNING: leafHash must be computed in such a way that it cannot be a non-leaf hash.
function computeRootUnsafe(
MerkleProof memory proof,
uint256 index,
bytes32 leafHash,
string memory prefix
) internal pure returns (bytes32 h) {
h = leafHash;
for (uint256 layer = 0; layer < proof.counterparts.length; layer++) {
if (index & 1 == 0) {
h = keccak256(abi.encodePacked(prefix, h, proof.counterparts[layer]));
} else {
h = keccak256(abi.encodePacked(prefix, proof.counterparts[layer], h));
}
index >>= 1;
}
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "./Value.sol";
import "./ValueStack.sol";
import "./Machine.sol";
import "./Instructions.sol";
import "./StackFrame.sol";
import "./MerkleProof.sol";
import "./ModuleMemory.sol";
import "./Module.sol";
import "./GlobalState.sol";
library Deserialize {
function u8(bytes calldata proof, uint256 startOffset)
internal
pure
returns (uint8 ret, uint256 offset)
{
offset = startOffset;
ret = uint8(proof[offset]);
offset++;
}
function u16(bytes calldata proof, uint256 startOffset)
internal
pure
returns (uint16 ret, uint256 offset)
{
offset = startOffset;
for (uint256 i = 0; i < 16 / 8; i++) {
ret <<= 8;
ret |= uint8(proof[offset]);
offset++;
}
}
function u32(bytes calldata proof, uint256 startOffset)
internal
pure
returns (uint32 ret, uint256 offset)
{
offset = startOffset;
for (uint256 i = 0; i < 32 / 8; i++) {
ret <<= 8;
ret |= uint8(proof[offset]);
offset++;
}
}
function u64(bytes calldata proof, uint256 startOffset)
internal
pure
returns (uint64 ret, uint256 offset)
{
offset = startOffset;
for (uint256 i = 0; i < 64 / 8; i++) {
ret <<= 8;
ret |= uint8(proof[offset]);
offset++;
}
}
function u256(bytes calldata proof, uint256 startOffset)
internal
pure
returns (uint256 ret, uint256 offset)
{
offset = startOffset;
for (uint256 i = 0; i < 256 / 8; i++) {
ret <<= 8;
ret |= uint8(proof[offset]);
offset++;
}
}
function b32(bytes calldata proof, uint256 startOffset)
internal
pure
returns (bytes32 ret, uint256 offset)
{
offset = startOffset;
uint256 retInt;
(retInt, offset) = u256(proof, offset);
ret = bytes32(retInt);
}
function value(bytes calldata proof, uint256 startOffset)
internal
pure
returns (Value memory val, uint256 offset)
{
offset = startOffset;
uint8 typeInt = uint8(proof[offset]);
offset++;
require(typeInt <= uint8(ValueLib.maxValueType()), "BAD_VALUE_TYPE");
uint256 contents;
(contents, offset) = u256(proof, offset);
val = Value({valueType: ValueType(typeInt), contents: contents});
}
function valueStack(bytes calldata proof, uint256 startOffset)
internal
pure
returns (ValueStack memory stack, uint256 offset)
{
offset = startOffset;
bytes32 remainingHash;
(remainingHash, offset) = b32(proof, offset);
uint256 provedLength;
(provedLength, offset) = u256(proof, offset);
Value[] memory proved = new Value[](provedLength);
for (uint256 i = 0; i < proved.length; i++) {
(proved[i], offset) = value(proof, offset);
}
stack = ValueStack({proved: ValueArray(proved), remainingHash: remainingHash});
}
function instruction(bytes calldata proof, uint256 startOffset)
internal
pure
returns (Instruction memory inst, uint256 offset)
{
offset = startOffset;
uint16 opcode;
uint256 data;
(opcode, offset) = u16(proof, offset);
(data, offset) = u256(proof, offset);
inst = Instruction({opcode: opcode, argumentData: data});
}
function stackFrame(bytes calldata proof, uint256 startOffset)
internal
pure
returns (StackFrame memory window, uint256 offset)
{
offset = startOffset;
Value memory returnPc;
bytes32 localsMerkleRoot;
uint32 callerModule;
uint32 callerModuleInternals;
(returnPc, offset) = value(proof, offset);
(localsMerkleRoot, offset) = b32(proof, offset);
(callerModule, offset) = u32(proof, offset);
(callerModuleInternals, offset) = u32(proof, offset);
window = StackFrame({
returnPc: returnPc,
localsMerkleRoot: localsMerkleRoot,
callerModule: callerModule,
callerModuleInternals: callerModuleInternals
});
}
function stackFrameWindow(bytes calldata proof, uint256 startOffset)
internal
pure
returns (StackFrameWindow memory window, uint256 offset)
{
offset = startOffset;
bytes32 remainingHash;
(remainingHash, offset) = b32(proof, offset);
StackFrame[] memory proved;
if (proof[offset] != 0) {
offset++;
proved = new StackFrame[](1);
(proved[0], offset) = stackFrame(proof, offset);
} else {
offset++;
proved = new StackFrame[](0);
}
window = StackFrameWindow({proved: proved, remainingHash: remainingHash});
}
function moduleMemory(bytes calldata proof, uint256 startOffset)
internal
pure
returns (ModuleMemory memory mem, uint256 offset)
{
offset = startOffset;
uint64 size;
uint64 maxSize;
bytes32 root;
(size, offset) = u64(proof, offset);
(maxSize, offset) = u64(proof, offset);
(root, offset) = b32(proof, offset);
mem = ModuleMemory({size: size, maxSize: maxSize, merkleRoot: root});
}
function module(bytes calldata proof, uint256 startOffset)
internal
pure
returns (Module memory mod, uint256 offset)
{
offset = startOffset;
bytes32 globalsMerkleRoot;
ModuleMemory memory mem;
bytes32 tablesMerkleRoot;
bytes32 functionsMerkleRoot;
uint32 internalsOffset;
(globalsMerkleRoot, offset) = b32(proof, offset);
(mem, offset) = moduleMemory(proof, offset);
(tablesMerkleRoot, offset) = b32(proof, offset);
(functionsMerkleRoot, offset) = b32(proof, offset);
(internalsOffset, offset) = u32(proof, offset);
mod = Module({
globalsMerkleRoot: globalsMerkleRoot,
moduleMemory: mem,
tablesMerkleRoot: tablesMerkleRoot,
functionsMerkleRoot: functionsMerkleRoot,
internalsOffset: internalsOffset
});
}
function globalState(bytes calldata proof, uint256 startOffset)
internal
pure
returns (GlobalState memory state, uint256 offset)
{
offset = startOffset;
// using constant ints for array size requires newer solidity
bytes32[2] memory bytes32Vals;
uint64[2] memory u64Vals;
for (uint8 i = 0; i < GlobalStateLib.BYTES32_VALS_NUM; i++) {
(bytes32Vals[i], offset) = b32(proof, offset);
}
for (uint8 i = 0; i < GlobalStateLib.U64_VALS_NUM; i++) {
(u64Vals[i], offset) = u64(proof, offset);
}
state = GlobalState({bytes32Vals: bytes32Vals, u64Vals: u64Vals});
}
function machine(bytes calldata proof, uint256 startOffset)
internal
pure
returns (Machine memory mach, uint256 offset)
{
offset = startOffset;
MachineStatus status;
{
uint8 statusU8;
(statusU8, offset) = u8(proof, offset);
if (statusU8 == 0) {
status = MachineStatus.RUNNING;
} else if (statusU8 == 1) {
status = MachineStatus.FINISHED;
} else if (statusU8 == 2) {
status = MachineStatus.ERRORED;
} else if (statusU8 == 3) {
status = MachineStatus.TOO_FAR;
} else {
revert("UNKNOWN_MACH_STATUS");
}
}
ValueStack memory values;
ValueStack memory internalStack;
bytes32 globalStateHash;
uint32 moduleIdx;
uint32 functionIdx;
uint32 functionPc;
StackFrameWindow memory frameStack;
bytes32 modulesRoot;
(values, offset) = valueStack(proof, offset);
(internalStack, offset) = valueStack(proof, offset);
(frameStack, offset) = stackFrameWindow(proof, offset);
(globalStateHash, offset) = b32(proof, offset);
(moduleIdx, offset) = u32(proof, offset);
(functionIdx, offset) = u32(proof, offset);
(functionPc, offset) = u32(proof, offset);
(modulesRoot, offset) = b32(proof, offset);
mach = Machine({
status: status,
valueStack: values,
internalStack: internalStack,
frameStack: frameStack,
globalStateHash: globalStateHash,
moduleIdx: moduleIdx,
functionIdx: functionIdx,
functionPc: functionPc,
modulesRoot: modulesRoot
});
}
function merkleProof(bytes calldata proof, uint256 startOffset)
internal
pure
returns (MerkleProof memory merkle, uint256 offset)
{
offset = startOffset;
uint8 length;
(length, offset) = u8(proof, offset);
bytes32[] memory counterparts = new bytes32[](length);
for (uint8 i = 0; i < length; i++) {
(counterparts[i], offset) = b32(proof, offset);
}
merkle = MerkleProof(counterparts);
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
struct Node {
// Hash of the state of the chain as of this node
bytes32 stateHash;
// Hash of the data that can be challenged
bytes32 challengeHash;
// Hash of the data that will be committed if this node is confirmed
bytes32 confirmData;
// Index of the node previous to this one
uint64 prevNum;
// Deadline at which this node can be confirmed
uint64 deadlineBlock;
// Deadline at which a child of this node can be confirmed
uint64 noChildConfirmedBeforeBlock;
// Number of stakers staked on this node. This includes real stakers and zombies
uint64 stakerCount;
// Number of stakers staked on a child node. This includes real stakers and zombies
uint64 childStakerCount;
// This value starts at zero and is set to a value when the first child is created. After that it is constant until the node is destroyed or the owner destroys pending nodes
uint64 firstChildBlock;
// The number of the latest child of this node to be created
uint64 latestChildNumber;
// The block number when this node was created
uint64 createdAtBlock;
// A hash of all the data needed to determine this node's validity, to protect against reorgs
bytes32 nodeHash;
}
/**
* @notice Utility functions for Node
*/
library NodeLib {
/**
* @notice Initialize a Node
* @param _stateHash Initial value of stateHash
* @param _challengeHash Initial value of challengeHash
* @param _confirmData Initial value of confirmData
* @param _prevNum Initial value of prevNum
* @param _deadlineBlock Initial value of deadlineBlock
* @param _nodeHash Initial value of nodeHash
*/
function createNode(
bytes32 _stateHash,
bytes32 _challengeHash,
bytes32 _confirmData,
uint64 _prevNum,
uint64 _deadlineBlock,
bytes32 _nodeHash
) internal view returns (Node memory) {
Node memory node;
node.stateHash = _stateHash;
node.challengeHash = _challengeHash;
node.confirmData = _confirmData;
node.prevNum = _prevNum;
node.deadlineBlock = _deadlineBlock;
node.noChildConfirmedBeforeBlock = _deadlineBlock;
node.createdAtBlock = uint64(block.number);
node.nodeHash = _nodeHash;
return node;
}
/**
* @notice Update child properties
* @param number The child number to set
*/
function childCreated(Node storage self, uint64 number) internal {
if (self.firstChildBlock == 0) {
self.firstChildBlock = uint64(block.number);
}
self.latestChildNumber = number;
}
/**
* @notice Update the child confirmed deadline
* @param deadline The new deadline to set
*/
function newChildConfirmDeadline(Node storage self, uint64 deadline) internal {
self.noChildConfirmedBeforeBlock = deadline;
}
/**
* @notice Check whether the current block number has met or passed the node's deadline
*/
function requirePastDeadline(Node memory self) internal view {
require(block.number >= self.deadlineBlock, "BEFORE_DEADLINE");
}
/**
* @notice Check whether the current block number has met or passed deadline for children of this node to be confirmed
*/
function requirePastChildConfirmDeadline(Node memory self) internal view {
require(block.number >= self.noChildConfirmedBeforeBlock, "CHILD_TOO_RECENT");
}
}
File 5 of 5: Bridge
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import {
NotContract,
NotRollupOrOwner,
NotDelayedInbox,
NotSequencerInbox,
NotOutbox,
InvalidOutboxSet,
BadSequencerMessageNumber
} from "../libraries/Error.sol";
import "./IBridge.sol";
import "./Messages.sol";
import "../libraries/DelegateCallAware.sol";
import {L1MessageType_batchPostingReport} from "../libraries/MessageTypes.sol";
/**
* @title Staging ground for incoming and outgoing messages
* @notice Holds the inbox accumulator for sequenced and delayed messages.
* It is also the ETH escrow for value sent with these messages.
* Since the escrow is held here, this contract also contains a list of allowed
* outboxes that can make calls from here and withdraw this escrow.
*/
contract Bridge is Initializable, DelegateCallAware, IBridge {
using AddressUpgradeable for address;
struct InOutInfo {
uint256 index;
bool allowed;
}
mapping(address => InOutInfo) private allowedDelayedInboxesMap;
mapping(address => InOutInfo) private allowedOutboxesMap;
address[] public allowedDelayedInboxList;
address[] public allowedOutboxList;
address private _activeOutbox;
/// @inheritdoc IBridge
bytes32[] public delayedInboxAccs;
/// @inheritdoc IBridge
bytes32[] public sequencerInboxAccs;
IOwnable public rollup;
address public sequencerInbox;
uint256 public override sequencerReportedSubMessageCount;
address private constant EMPTY_ACTIVEOUTBOX = address(type(uint160).max);
function initialize(IOwnable rollup_) external initializer onlyDelegated {
_activeOutbox = EMPTY_ACTIVEOUTBOX;
rollup = rollup_;
}
modifier onlyRollupOrOwner() {
if (msg.sender != address(rollup)) {
address rollupOwner = rollup.owner();
if (msg.sender != rollupOwner) {
revert NotRollupOrOwner(msg.sender, address(rollup), rollupOwner);
}
}
_;
}
/// @dev returns the address of current active Outbox, or zero if no outbox is active
function activeOutbox() public view returns (address) {
address outbox = _activeOutbox;
// address zero is returned if no outbox is set, but the value used in storage
// is non-zero to save users some gas (as storage refunds are usually maxed out)
// EIP-1153 would help here.
// we don't return `EMPTY_ACTIVEOUTBOX` to avoid a breaking change on the current api
if (outbox == EMPTY_ACTIVEOUTBOX) return address(0);
return outbox;
}
function allowedDelayedInboxes(address inbox) external view returns (bool) {
return allowedDelayedInboxesMap[inbox].allowed;
}
function allowedOutboxes(address outbox) external view returns (bool) {
return allowedOutboxesMap[outbox].allowed;
}
modifier onlySequencerInbox() {
if (msg.sender != sequencerInbox) revert NotSequencerInbox(msg.sender);
_;
}
function enqueueSequencerMessage(
bytes32 dataHash,
uint256 afterDelayedMessagesRead,
uint256 prevMessageCount,
uint256 newMessageCount
)
external
onlySequencerInbox
returns (
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 acc
)
{
if (
sequencerReportedSubMessageCount != prevMessageCount &&
prevMessageCount != 0 &&
sequencerReportedSubMessageCount != 0
) {
revert BadSequencerMessageNumber(sequencerReportedSubMessageCount, prevMessageCount);
}
sequencerReportedSubMessageCount = newMessageCount;
seqMessageIndex = sequencerInboxAccs.length;
if (sequencerInboxAccs.length > 0) {
beforeAcc = sequencerInboxAccs[sequencerInboxAccs.length - 1];
}
if (afterDelayedMessagesRead > 0) {
delayedAcc = delayedInboxAccs[afterDelayedMessagesRead - 1];
}
acc = keccak256(abi.encodePacked(beforeAcc, dataHash, delayedAcc));
sequencerInboxAccs.push(acc);
}
/// @inheritdoc IBridge
function submitBatchSpendingReport(address sender, bytes32 messageDataHash)
external
onlySequencerInbox
returns (uint256)
{
return
addMessageToDelayedAccumulator(
L1MessageType_batchPostingReport,
sender,
uint64(block.number),
uint64(block.timestamp), // solhint-disable-line not-rely-on-time,
block.basefee,
messageDataHash
);
}
/// @inheritdoc IBridge
function enqueueDelayedMessage(
uint8 kind,
address sender,
bytes32 messageDataHash
) external payable returns (uint256) {
if (!allowedDelayedInboxesMap[msg.sender].allowed) revert NotDelayedInbox(msg.sender);
return
addMessageToDelayedAccumulator(
kind,
sender,
uint64(block.number),
uint64(block.timestamp), // solhint-disable-line not-rely-on-time
block.basefee,
messageDataHash
);
}
function addMessageToDelayedAccumulator(
uint8 kind,
address sender,
uint64 blockNumber,
uint64 blockTimestamp,
uint256 baseFeeL1,
bytes32 messageDataHash
) internal returns (uint256) {
uint256 count = delayedInboxAccs.length;
bytes32 messageHash = Messages.messageHash(
kind,
sender,
blockNumber,
blockTimestamp,
count,
baseFeeL1,
messageDataHash
);
bytes32 prevAcc = 0;
if (count > 0) {
prevAcc = delayedInboxAccs[count - 1];
}
delayedInboxAccs.push(Messages.accumulateInboxMessage(prevAcc, messageHash));
emit MessageDelivered(
count,
prevAcc,
msg.sender,
kind,
sender,
messageDataHash,
baseFeeL1,
blockTimestamp
);
return count;
}
function executeCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool success, bytes memory returnData) {
if (!allowedOutboxesMap[msg.sender].allowed) revert NotOutbox(msg.sender);
if (data.length > 0 && !to.isContract()) revert NotContract(to);
address prevOutbox = _activeOutbox;
_activeOutbox = msg.sender;
// We set and reset active outbox around external call so activeOutbox remains valid during call
// We use a low level call here since we want to bubble up whether it succeeded or failed to the caller
// rather than reverting on failure as well as allow contract and non-contract calls
// solhint-disable-next-line avoid-low-level-calls
(success, returnData) = to.call{value: value}(data);
_activeOutbox = prevOutbox;
emit BridgeCallTriggered(msg.sender, to, value, data);
}
function setSequencerInbox(address _sequencerInbox) external onlyRollupOrOwner {
sequencerInbox = _sequencerInbox;
emit SequencerInboxUpdated(_sequencerInbox);
}
function setDelayedInbox(address inbox, bool enabled) external onlyRollupOrOwner {
InOutInfo storage info = allowedDelayedInboxesMap[inbox];
bool alreadyEnabled = info.allowed;
emit InboxToggle(inbox, enabled);
if ((alreadyEnabled && enabled) || (!alreadyEnabled && !enabled)) {
return;
}
if (enabled) {
allowedDelayedInboxesMap[inbox] = InOutInfo(allowedDelayedInboxList.length, true);
allowedDelayedInboxList.push(inbox);
} else {
allowedDelayedInboxList[info.index] = allowedDelayedInboxList[
allowedDelayedInboxList.length - 1
];
allowedDelayedInboxesMap[allowedDelayedInboxList[info.index]].index = info.index;
allowedDelayedInboxList.pop();
delete allowedDelayedInboxesMap[inbox];
}
}
function setOutbox(address outbox, bool enabled) external onlyRollupOrOwner {
if (outbox == EMPTY_ACTIVEOUTBOX) revert InvalidOutboxSet(outbox);
InOutInfo storage info = allowedOutboxesMap[outbox];
bool alreadyEnabled = info.allowed;
emit OutboxToggle(outbox, enabled);
if ((alreadyEnabled && enabled) || (!alreadyEnabled && !enabled)) {
return;
}
if (enabled) {
allowedOutboxesMap[outbox] = InOutInfo(allowedOutboxList.length, true);
allowedOutboxList.push(outbox);
} else {
allowedOutboxList[info.index] = allowedOutboxList[allowedOutboxList.length - 1];
allowedOutboxesMap[allowedOutboxList[info.index]].index = info.index;
allowedOutboxList.pop();
delete allowedOutboxesMap[outbox];
}
}
function setSequencerReportedSubMessageCount(uint256 newMsgCount) external onlyRollupOrOwner {
sequencerReportedSubMessageCount = newMsgCount;
}
function delayedMessageCount() external view override returns (uint256) {
return delayedInboxAccs.length;
}
function sequencerMessageCount() external view returns (uint256) {
return sequencerInboxAccs.length;
}
/// @dev For the classic -> nitro migration. TODO: remove post-migration.
function acceptFundsFromOldBridge() external payable {}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 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");
(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");
(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");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal 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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
/// @dev Init was already called
error AlreadyInit();
/// Init was called with param set to zero that must be nonzero
error HadZeroInit();
/// @dev Thrown when non owner tries to access an only-owner function
/// @param sender The msg.sender who is not the owner
/// @param owner The owner address
error NotOwner(address sender, address owner);
/// @dev Thrown when an address that is not the rollup tries to call an only-rollup function
/// @param sender The sender who is not the rollup
/// @param rollup The rollup address authorized to call this function
error NotRollup(address sender, address rollup);
/// @dev Thrown when the contract was not called directly from the origin ie msg.sender != tx.origin
error NotOrigin();
/// @dev Provided data was too large
/// @param dataLength The length of the data that is too large
/// @param maxDataLength The max length the data can be
error DataTooLarge(uint256 dataLength, uint256 maxDataLength);
/// @dev The provided is not a contract and was expected to be
/// @param addr The adddress in question
error NotContract(address addr);
/// @dev The merkle proof provided was too long
/// @param actualLength The length of the merkle proof provided
/// @param maxProofLength The max length a merkle proof can have
error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
/// @dev Thrown when an un-authorized address tries to access an admin function
/// @param sender The un-authorized sender
/// @param rollup The rollup, which would be authorized
/// @param owner The rollup's owner, which would be authorized
error NotRollupOrOwner(address sender, address rollup, address owner);
// Bridge Errors
/// @dev Thrown when an un-authorized address tries to access an only-inbox function
/// @param sender The un-authorized sender
error NotDelayedInbox(address sender);
/// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
/// @param sender The un-authorized sender
error NotSequencerInbox(address sender);
/// @dev Thrown when an un-authorized address tries to access an only-outbox function
/// @param sender The un-authorized sender
error NotOutbox(address sender);
/// @dev the provided outbox address isn't valid
/// @param outbox address of outbox being set
error InvalidOutboxSet(address outbox);
// Inbox Errors
/// @dev The contract is paused, so cannot be paused
error AlreadyPaused();
/// @dev The contract is unpaused, so cannot be unpaused
error AlreadyUnpaused();
/// @dev The contract is paused
error Paused();
/// @dev msg.value sent to the inbox isn't high enough
error InsufficientValue(uint256 expected, uint256 actual);
/// @dev submission cost provided isn't enough to create retryable ticket
error InsufficientSubmissionCost(uint256 expected, uint256 actual);
/// @dev address not allowed to interact with the given contract
error NotAllowedOrigin(address origin);
/// @dev used to convey retryable tx data in eth calls without requiring a tx trace
/// this follows a pattern similar to EIP-3668 where reverts surface call information
error RetryableData(
address from,
address to,
uint256 l2CallValue,
uint256 deposit,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes data
);
// Outbox Errors
/// @dev The provided proof was too long
/// @param proofLength The length of the too-long proof
error ProofTooLong(uint256 proofLength);
/// @dev The output index was greater than the maximum
/// @param index The output index
/// @param maxIndex The max the index could be
error PathNotMinimal(uint256 index, uint256 maxIndex);
/// @dev The calculated root does not exist
/// @param root The calculated root
error UnknownRoot(bytes32 root);
/// @dev The record has already been spent
/// @param index The index of the spent record
error AlreadySpent(uint256 index);
/// @dev A call to the bridge failed with no return data
error BridgeCallFailed();
// Sequencer Inbox Errors
/// @dev Thrown when someone attempts to read fewer messages than have already been read
error DelayedBackwards();
/// @dev Thrown when someone attempts to read more messages than exist
error DelayedTooFar();
/// @dev Force include can only read messages more blocks old than the delay period
error ForceIncludeBlockTooSoon();
/// @dev Force include can only read messages more seconds old than the delay period
error ForceIncludeTimeTooSoon();
/// @dev The message provided did not match the hash in the delayed inbox
error IncorrectMessagePreimage();
/// @dev This can only be called by the batch poster
error NotBatchPoster();
/// @dev The sequence number provided to this message was inconsistent with the number of batches already included
error BadSequencerNumber(uint256 stored, uint256 received);
/// @dev The sequence message number provided to this message was inconsistent with the previous one
error BadSequencerMessageNumber(uint256 stored, uint256 received);
/// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
error DataNotAuthenticated();
/// @dev Tried to create an already valid Data Availability Service keyset
error AlreadyValidDASKeyset(bytes32);
/// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
error NoSuchKeyset(bytes32);
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IOwnable.sol";
interface IBridge {
event MessageDelivered(
uint256 indexed messageIndex,
bytes32 indexed beforeInboxAcc,
address inbox,
uint8 kind,
address sender,
bytes32 messageDataHash,
uint256 baseFeeL1,
uint64 timestamp
);
event BridgeCallTriggered(
address indexed outbox,
address indexed to,
uint256 value,
bytes data
);
event InboxToggle(address indexed inbox, bool enabled);
event OutboxToggle(address indexed outbox, bool enabled);
event SequencerInboxUpdated(address newSequencerInbox);
function allowedDelayedInboxList(uint256) external returns (address);
function allowedOutboxList(uint256) external returns (address);
/// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function delayedInboxAccs(uint256) external view returns (bytes32);
/// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function sequencerInboxAccs(uint256) external view returns (bytes32);
function rollup() external view returns (IOwnable);
function sequencerInbox() external view returns (address);
function activeOutbox() external view returns (address);
function allowedDelayedInboxes(address inbox) external view returns (bool);
function allowedOutboxes(address outbox) external view returns (bool);
function sequencerReportedSubMessageCount() external view returns (uint256);
/**
* @dev Enqueue a message in the delayed inbox accumulator.
* These messages are later sequenced in the SequencerInbox, either
* by the sequencer as part of a normal batch, or by force inclusion.
*/
function enqueueDelayedMessage(
uint8 kind,
address sender,
bytes32 messageDataHash
) external payable returns (uint256);
function executeCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool success, bytes memory returnData);
function delayedMessageCount() external view returns (uint256);
function sequencerMessageCount() external view returns (uint256);
// ---------- onlySequencerInbox functions ----------
function enqueueSequencerMessage(
bytes32 dataHash,
uint256 afterDelayedMessagesRead,
uint256 prevMessageCount,
uint256 newMessageCount
)
external
returns (
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 acc
);
/**
* @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
* This is done through a separate function entrypoint instead of allowing the sequencer inbox
* to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
* every delayed inbox or every sequencer inbox call.
*/
function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
external
returns (uint256 msgNum);
// ---------- onlyRollupOrOwner functions ----------
function setSequencerInbox(address _sequencerInbox) external;
function setDelayedInbox(address inbox, bool enabled) external;
function setOutbox(address inbox, bool enabled) external;
// ---------- initializer ----------
function initialize(IOwnable rollup_) external;
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library Messages {
function messageHash(
uint8 kind,
address sender,
uint64 blockNumber,
uint64 timestamp,
uint256 inboxSeqNum,
uint256 baseFeeL1,
bytes32 messageDataHash
) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
kind,
sender,
blockNumber,
timestamp,
inboxSeqNum,
baseFeeL1,
messageDataHash
)
);
}
function accumulateInboxMessage(bytes32 prevAcc, bytes32 message)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(prevAcc, message));
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {NotOwner} from "./Error.sol";
/// @dev A stateless contract that allows you to infer if the current call has been delegated or not
/// Pattern used here is from UUPS implementation by the OpenZeppelin team
abstract contract DelegateCallAware {
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegate call. This allows a function to be
* callable on the proxy contract but not on the logic contract.
*/
modifier onlyDelegated() {
require(address(this) != __self, "Function must be called through delegatecall");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "Function must not be called through delegatecall");
_;
}
/// @dev Check that msg.sender is the current EIP 1967 proxy admin
modifier onlyProxyOwner() {
// Storage slot with the admin of the proxy contract
// This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1
bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
address admin;
assembly {
admin := sload(slot)
}
if (msg.sender != admin) revert NotOwner(msg.sender, admin);
_;
}
}
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
uint8 constant L2_MSG = 3;
uint8 constant L1MessageType_L2FundedByL1 = 7;
uint8 constant L1MessageType_submitRetryableTx = 9;
uint8 constant L1MessageType_ethDeposit = 12;
uint8 constant L1MessageType_batchPostingReport = 13;
uint8 constant L2MessageType_unsignedEOATx = 0;
uint8 constant L2MessageType_unsignedContractTx = 1;
uint8 constant ROLLUP_PROTOCOL_EVENT_TYPE = 8;
uint8 constant INITIALIZATION_MSG_TYPE = 11;
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.4.21 <0.9.0;
interface IOwnable {
function owner() external view returns (address);
}