Skip to main content

A synthetic evm bytecode generation library and cmdline utility to fuzz the ethereum stack machine

Project description

# evmcodegen

Ever wanted to generate and manipulate ethereum evm bytecode? This is your chance.

Use various strategies to generate Instructions, fix the stack layout, fix jump addresses, balance the stack and manipulate the code before serializing Instruction objects to bytecode.


## library

```python
import evmdasm
# import distribution and random codegen strategy
from evmcodegen.distributions import EVM_CATEGORY
from evmcodegen.generators.distribution import GaussDistrCodeGen
# import main codegen class
from evmcodegen.codegen import CodeGen

# prepare random number generators for stack arg generator

# Rnd is just a utility class providing random byte and number generators. see codegen.py
VALUEMAP ={
evmdasm.argtypes.Address: lambda: Rnd.byte_sequence(20),
evmdasm.argtypes.Word: lambda: Rnd.byte_sequence(32),
evmdasm.argtypes.Timestamp: lambda: Rnd.byte_sequence(4),
evmdasm.argtypes.Data: lambda: Rnd.byte_sequence(Rnd.uni_integer(0, Rnd.opcode())),
evmdasm.argtypes.CallValue: lambda: Rnd.uni_integer(0,1024),
evmdasm.argtypes.Gas: lambda: Rnd.uni_integer(0,1024),
evmdasm.argtypes.Length: lambda: Rnd.small_memory_length_1024(),
evmdasm.argtypes.MemOffset: lambda: Rnd.small_memory_length_1024(),
evmdasm.argtypes.Index256: lambda: Rnd.uni_integer(1,256),
evmdasm.argtypes.Index64: lambda: Rnd.uni_integer(1,64),
evmdasm.argtypes.Index32: lambda: Rnd.length_32(),
evmdasm.argtypes.Byte: lambda: Rnd.byte_sequence(1),
evmdasm.argtypes.Bool: lambda: Rnd.byte_sequence(1),
evmdasm.argtypes.Value: lambda: Rnd.uni_integer(),
#evmdasm.argtypes.Label: lambda: 0xc0fefefe, # this is handled by fix_code_layout (fix jumps)
}

# create random number generator
rnd_codegen = GaussDistrCodeGen(distribution=EVM_CATEGORY)

# generate code, fix stack arguments, make jumps land on jumpdests, fix stack balance
evmcode = CodeGen()\
.generate(generator=rnd_codegen, length=None, min_gas=20)\
.fix_stack_arguments(valuemap=VALUEMAP)\
.fix_jumps().fix_stack_balance()

# print evmcode as string
print("0x%s" % evmcode.assemble().as_hexstring)

# disassemble and print listing
print(evmcode.reassemble().instructions.as_string)

# print some stats
print(CodeGen.stats(evmcode))
```



## cmdline

`python -m evmcodegen [--disassemble] [--count 1] [--stats]`

```
Usage: __main__.py [options]

Options:
-h, --help show this help message and exit
-v VERBOSITY, --verbosity=VERBOSITY
available loglevels:
critical,fatal,error,warning,warn,info,debug,notset
[default: critical]
-g GENERATOR, --generator=GENERATOR
select generator (default: DistrCategory)
-d, --disassemble show disassembly
-c COUNT, --count=COUNT
number of evmcodes to generate
-m MIN_GAS, --min-gas=MIN_GAS
generate instructions consuming at least this amount
of gas
-l LENGTH, --length=LENGTH
instructions per generated code
-s, --stats show statistics
-b, --balance balance the stack
```


```
#> python3 -m evmcodegen --disassemble --stats
0x614e7e674fb87cc2d90eda346716ddb46d033b432f1677e1183a7c67c851296d5e7665ca56e7dd2158341bdb43fac760af6103486101546102dc73f9be0ce6ff661facc3be2288534765a056c1ac81610169f46e8d4b95ce3bd940e60687688ec7d9b6771bb0d8b79e269479c5828966eb6449d66f267a852493302062d35abc7c9b12b8365060660f8462edfefc847086df38ccd44a9d262a1dd50555b8692e2eddd62e1cbb07c9a66b9a237026291f95884b8fe26673544d46c8936bea177da53e3c1312bda38f4f3ba068f5e8a91c3bc73e67097af9f36c4e149ef38103c0552d7e092461a137d5c499717f923f5f2f65b6f992507ee17c0b6c470b9a437ad922daacd9285ef18b6edd4eab3613ab326052e3c80268e0b0d6226bb814137a6ac1987fc7638244c9442b4766d5a92878349dd88d67b6eef9a072a2abcd67a13f347c0bb492090a767b52cecf065119c1819a817d07ee8cc663a26ec09c089b682696cf5a850c1df1956fe90bff18d0ff36bfa6f2cc25b1b6084973dacbe5081a45f170b8743ed31da4d868e7932dd672c767f9ac5e9d68488912397af74cf68c291efe6d95e3d53d0037474e40edd89d6800756622c06f5860c016f8a9bbddb445a54a6ea769cc97d77382e2f2409561485dbfc9d3932cdd0fb9eac8151d6705bb89ddcd62ce987295c6dd56a8576d09e0cf2c6f3cc6fdf304d8f46e402e6f145a4c4a18e3cbeb7d6e687c997fc1efa359cdbae6d6e94c6744813fce07d2a7f3383cddb72a4c2023a8f9b13f2160111a672eff1825f5f63a7060381b7ec873b9effc596d42b79b14c4cef32881f60d56d1b91327bd9f6a028fb7f368677d1cfb92b27e2c4567cddfd280cc1ddbe005669629f47fd4dad6716783221dc1365aab2ae1e7bc159e34ec7b5a7ef5cb22fa8d05b913633446eef412e7d0223ec9d074b394243cb6bffe50480964bc6cb6ddf466c8e538144689ea7211c96372ebc885616f7dd41fd042a7ba43924b60326d3acd754d74fa71b796af1a31242865a44b109783b1693c3d2328e1087053765777466acf1d7452e1afb94c796ab44aa15e0de41a68794244498a610175610234605660f4737ddfeaa60e0f7c11a55b0b9ecb916a20b4440321610232fa7616c7d32909fda17ea5607c092368f5688aa4f467419d2a7614af7b38397918168266194e2434a26ea778325032e92f694bc64af97e6a90cd99307286a57fa21f7ed5e4aeb515fa0767cada6e24417c55aec3ab25899625c0ad520fe7bf5677ac7a22c2354b9bc9532bbe3eae77eea0ab6970e7e5428c0e7b512d34d3b6e2de69d16b508c6c6572d362e053e37e0f9f52e65303c6ff3971bb8b7dbd5a625d7242adeaf416ac2456373c1ab8876f9409961b905c1611140503c2e7b9f704643739a023d76e275efe1c6251b587abddcfaeb7deb37790db00fa123831109180c415126d9262c00f769776116be071792053dc741d6e73e636af254454fe9a6e399b725a8485c58eb2878c36f17a310f639dac7f21006724b580b8325975a567d7ca284dbc23d4d3016466dbe5ca2368cfa91172680d19d4136caef0be5d7ed702b37255abd4aa772857ae2297daad62f07a6063ae30908b740a3ac8e2691665799482d82cc63b3b2daed9c2f21957ecff0cd85216892d2e0af5556c0e331fca8ff6e733c2e8a4b7a07a19846867032e5c38a4c5056b055709854d2993b7cd8e697789efeb7d1d7a65f900cf089325cfb8121835a9816eda7549edc1abe985e221e28f0c786d345c855814c11a2abd676c33a780214952e878ec45572302653abe579a1c937063d8bf40b064442432e4cbb9b74d1f132473f771f13bc5f84a7b41096d5401047ba6aa334c39723f03e6e653a59d306946c884c09483c672d14d75abee3419c0f7fa908d937873a33ced37d9d80f8cb3938cb06235121e6f8df92a829997b46037fe84191e5062ce63e4f720cb605d70e48d647f383d36b4133b7d314cc0b326536a46925961523d9ea5334f9c7abde8e68ad35da5b588b3ee872f45e29e6bdeec35cee0b5e2a02efe7657045b3a15e3caba15477789cdfb96faa1e8dc247e81c57a5b7c1018dc480354c9d78bf90d4dbea5d8276a05001bb9757e61858878620ae1d95f3f20137d9ad620d6ec3259229f7e7bbc6a25387a64416c4fdc2c8167a286e57a68fd156667360ca24fc4ef6e6f01586f07a4a68a53095213ac0a1ec4c63b390a67e0702cbc9dd2db4370d1d9c7a5b6c3da0f4b1ef3252f64f631ef70e4b6872c3306d6507bac70dcb6cae75a3d612f81686ac01b77c2385feb636e34578695d41d7fae50b0177d820edb66fa1ae494b0e20f722d7df2f33f71e32b1e492e8c9d7b7029c166108767b7b64cd1d3a5de76676ec74072beacb6d90367d2f8194272b6731167696234bc8e84f3a00a7249c17b5dc6863addf72a8324c58cc01340108171d40d90699aea0adba797accae7e6616c35537ee43b5a12488c9416d52e0f76c8fbc332ef5f3850507d04fcf102d651bb44c66236eaa1658f48355516de7d2c34f78a8cc7862d3fa05b9f8f6852fcd36482d7da0d425b40b215b4573a726ceba7698bf0c62ada3b724ad31ea661f42104657b5370035e108668a88a98c8bc18bb6db678abf4ff881f53f9e3c7a4c7fbe482ab330c98ce7a9eeb2102d06bded846d30d932e36c2ecac02742fbd160a8990ced7c66cc38a83d5bf21ec0e96ceb46ba2dd9b5fdec8c0c7969da667788fab6ab68b7cb6479878e0bcd69adc11fe7ec5c18c5b447b52857ea959de88411e12fa0908f9807461e3fed1116129096a767b492a5fbc958b8275eb0fc381e5604161cebe13effb66844c3030018a47e87b9008ea24ec51ad6e95cb40e61365f2e80e47898ad8749788af7ced6f7ab6b62f9cf38da85bb1e8ea46a7640a4754fcba282e29b9ac24cfdf79342d504c84e11afd0ed5de832538537e0c750ca9855719cf7962606a61b15863a159e3237d5bd94d2d674e3fbf4ccd30b099cb9240745a6715a253216cec32d688251b662fbabe3b84f6b174b1c2a915041018e0238607eb112e0586179759ef676ef04c21885a6d2f480d9bce417bef0c6bf45265629bdc2a1adf86bed5638c6ecdbd648621d8c0597dc818794b717d627ac4eeb85e9e2a9b46560ebd30fec878fd3d5e4649bbd27224415f91cd46fd7c093953fb0c27e86947a5f87c5c7e6ebb18a6b1e471f27fa66459e9474e3c819a9d96b534fd903618b18f7f92c89f3ec163fd638b111005482a5b72a5014bb492f5c5ff747ccf49f41d63e26102ae526965f40937e340da863f81722087d5b5a516f0658563fdd66cbe0fa4e13c08639a31ad4f62d8f9b77597034e0361d3e171443b1e2b3083303e76663431c8c37d453f0cd493f6b9f17e8cd17a058112fc1a20dd0ece0716971afa605b349d7d9c6f785d0400507952790f320d0194a495169976cf5250eefeb4a04113c86ce4b62979b0e9a6dcb70caab216867938c8922d460de3dbcee01ffd7d4f4f551de52b20b75c9862b10861568f61417f72e044009acb3fb9a5fd63413263f22d665683817483729635b6d26dfcaed800ae61c8e8789b5ee2c5006e35ccfc07243e42e6b0fe3c406f15d36766a591da19351ac161997e6a916f3ebfde35c08852ab10701766c26963cc764b44077b54c9ef2413556074782a4492bc74ca6bac70815334e890b5ac92372e6ec9f0506d949a7bb3cd34a9aeb9f5b294c180a5a848007158848c4f666c5a95b9680c6460656cea6adc8128cf52dd2e84bae842768fa76642dc01f2d3a05ac2063028d23d708199fde458b27276475ebf33ec30842bcc380b1279978f166dc17ce4ef2b78f042ee40f6f648f2156e3a5d70d8cd45bd5aeaf00a0fdaccca6ea0546dd6255bd023e3d0c4349feb41768202b9dfdebb598076629896f396f7617bcabd871c4a6f705d7c1a2dbba290c5f78d33e00f984db8f06e5928a2a036dcf8d9847c19329008385b6b8875d837c071af125e4689fa6fabeb05d59f99d91235c9498d9f0b6840612ea7674d3181eb93d392056b0f4fcd6cdfc6c3b52dd7bae577acecb7b89afb3bfa649eb54556c46965c8dd03e2694bf2918f675d56fa78678618b967ede7294a785b8bd50a6439c11e4d4e7564902e8cd1a08463692c006fa0d755fdcb10f41b40446289fbbb77763f4b6e4d4da5f232453836b6d9dda3ec471281995425e369c6e8fe3fa3770b9e1ec47cd694cd5c180e0441808788e7725ff2922f886dfef2d30e3648a3188dec85674c7bca12d270cf0660271d6d8138f0eeef0762bcb3bf6128cb35637864aede6eb33318f9f20a99a2e23cb4ff0390f9624cbd436c9124665f674ccd5e00d8266e3671285192746418db51770305278afbcff92a5f6c61e70a1ec48a4b0f33b4074e817e1d14c1c3a4a41981ee6625d76a019784b20cf96b2dd21848df410f820e06c572b3316b4d3dec7371c7b07f5577d24d8042ee146b866c57ace761707ba5973722682b1d089d8dea40dfcf77380cd370fa76126d75d3fe6732b5d785144b5e6f514cbbfb6eb779942d0cd125b32b3f59eefc4fb5646a620f46b87d10a23b5f4c6476bb89c06a648be10188604678b52ba30f1d383314b07acb8e676850d1b8f7bfd82167a04cc598e9a84bad17784c1e3347755cfd8fd26c4c9b70e719948d1cbc0168cbf8160d70abbe68e9dea8e76fec69c0b534b5808ecc73dd2d492b1b10ffa15ba915df6bcb8f7f6f41fc2e613d7f926cbe326d6b8fd58fcd0b748fbb78608d7443f7882ebadfe435d58c178c86eaebafebe85a0c8b7ddf9b92f76cb5728bc6fd5ca532ca8feda2cc0c25953ed138995b5a9d02d664dfdd8332ef6e81b07ac62801ea1572c5a93a20469d752bddecd288dc9243ee68c322bbb0ac3adb5e7cca18e4781e0400d6b9c7c995e53375970c41fa9e4c605f549a0d1f53c66ab71e88da1e3b8c56ab335d6b278b61371424002241a8ef366ac00fa026b2ae98b4f0c53d7c2466d509568b6caf9777dc9e19bbe6c8d64946acab33108d5ad9d330ba68f0ea9df868e64ee0ad9b6fed56eed7b69dc6c7a519c5f6718e4f9b7351dfc88d5f3641650f6fa8163ffceabd5b334358721fc48bd31dc940e908c69f93cc2097ef4b8bb56120e8836f9e059c17ffcf8dafef7cc220802c82b061014c610241610133606b61034273f3ed98ebab78edff68fac4c9b18dc2f5b6a4347161014bf16dc2354b19ff0d4c59dce1e35947d95a7af358e6f2ed512419114a3dc8a1ae4ec5ab7271fc217c9700607d886a09757aac215455d3ec455063c48ade0d7881630924faea8c68bfd4f220062b5330e22ab1d1ceab16a36983674962554eac60d93f61010560436733ee5f5c9a8c5381f57f3b1c188438b970ca725f2b9a016e671f43b26494d710620fc3fd19df81a4aca5600a1a67025c5fe6f4fea4f3602b1d6766c33ae872ea41c660131b61021a6103776101b761027361036e735d077d7663f53ec70b41abae8b0a109c65dc54da6059f26722145f28c90c737d60371c74956a872d666588335f9ac8e990b4eb9011db20027f673e16c9899327a94d6770cd7c350561524102674cf0574a8c77a38467bfbfe44d181a7c56077434c620e17e033fa5927682e0b361fcf47e841fa4fd7464edbed9a03b879c6d6a3476a06251635651400d9877df7b5e8e9ee836aa318cf1fd2ce32bf00daf82b63ada864675cceeebb24a3d318577d54cdab48a44c95db435153450686062a33bcfb1cbc1fe614db870480f4258805182c9928c07041d37ed501a6486f20c07d66331c1e11697693efa59b412e62fc5274f70852a665e5825dce97d050d14482c68524b67be652c3386e2504c671b311389fc872f2c670a8c90485e0b17670972e280113f62002796d7e98329e8c35ff819e26e67ab407b907cb3e9d860221b678244c7b2fd5c945c67f32dc3658b51cca1013366b042056b9383b5616c1c66b308784f3b902e9067c06734a487fa924767741896d5e005a5a019679afec2c3f805913d67e9424a573eead86b173861039c516758042c62dec84e29673c2f0bb106e77da20460056102586101636102ea61028a7305823d13750c52a0d30b4c44b53be166f70309186073f172cb89f890b6a5540ae4c312de2a3cd2595bad746ddcb1b65d944796c94189bd39083469c39a8118ef9edb102bde726bedbf94dbeb26c6ba0c91fd9304b196ab175c9178b5f8966bc3da11c999cc184140594a01861e6e17af7d7634ff5b677769f710916ea82e676bb979b030e3c28267d02d59055633109009608c67754b9ea70401143d7e4089086edfd90ce0d8366049bd4397d5d04a939bf679e1ff954276ffd6d0c16530843224bcaf6887a587cca7ea33dc448374047a234fadc1fc784e0767fd3f9f39f183eb26c7987639075f8e523515dc97250377f74a0f163e620a5f3637af67b939706d689f94bd6f5b35b361892425b6ae8a9b3559ebfab66fe0847a06b332514db64ac96f0e40b20793716368aba1c333679b2f2c15ce7f384c1d35e3674c69c7f8dc3b0a7e6706649863093b51cd067a952c7f11c1df13abde534d15ccbb09e277f66a16b0ee77cb97c52c7989e9c295a34a959514402e824c4abb0455162bf7b6c04cbc644061032b61038c608a61038a601a73ce69583f12f6d48a4f7de562f355b35f9b5195e761030af17d5634925b0386213f2b2fb8e26f5e60b34c18ce00909a2ad8cec8a53081bc66016fe284818f6a784a620a49ad1d7de1920be1da381d1e93963fd05633ba041d277256797380a4e0b01d687622177c077d52abd15b6b9fa90f0b81eb3df5067a223e7ccbbf6bf44cb34191be1616d9e08f03ee7921cf4d781bdd0830efc9894a7865ae569459bab308823ce2500dbb3e5983f639b2a6131e1eca70b857d9493f335fa7d1a7bbd512e4cf4c0c6bb83435111b2f55852a3114a969dea33c0a0aff18ee5a9d61b63f6fe4f1f421662a2f6643553479093e6f7f6a09f64b29bd7fa6c4133b026c51d0459e3ed94c2238b2061cb77e2b4ecc32e535695df0d73d7253b3e3940c915e31e8417f23d926adf8231da08e68f8596a52a31c861eb66c9784584eb7e8c5aad692bd5c3a64e798a8f71e720018d6b6a5da795631fcc5c6e7ddf41bed2a896248c474656d22d9f26f5f773ab6cffcff8dadeec02bdf48a7f41f8f3035a0005295f50267d4a9b6e11cce2efd71146327f7483889a45b2058e43664903d969b72eea84868227b3f84cf88ed608936d792cc1ed0616d0f9967eeeb1c4d2c55a4b86759415a4f8cdb173c0a67b633bd6f2b3c73a76786bf37cf7a512cbf027c030e7ed5f5e7e42918d7504bf48c4ac34b0b6db3c47e4f2ef7fffadde47dc61d86b3c3aafd8e1d9d6e022683cdaab9c3329f0f87c1439edbf8db9bcf61873a7ce6d56004b9e4768de2a0cfef48e48058f89d667bfb39ce107a1f8607fd72a73c57c4a8a4a09e44a9a673081ec7dfed96a36a1aa2625f9a2be10973af807221502ce8819d34e5ece6cff41df3e95dfbdb0c6ba1952e65688ecb17d7eb7f3464c984a6f0636b2d49bf5249b9e10624fb8fd86f88af35a4f378625e0749caca573777ad79af3ffc31d35c41300331d956e97eb384cd281bcacd35efe37b2a6934488379fe7f500c10ca7ebe6ea810eed8084200bb3601fcc83afc588da304aeb9bef03415d05dfcacdd6183779d7fe11d4c62c54f333421731c02cecc46363f5e6b4bcb28cb9a528c52969a49d4cc600f1a671577dd070215e6a967f81664a9ff35da960460f3616173576102b75160256103126101bf61029f73d029603eca1005d047272f02cf5473d14e03a67861035dfa695974e5b0fd90cd10302d678ba5346477d3550060271b71c8265616f9ee5e3533376dc06168395048ea7be4ad67bb093f69449b9efd2e8275882492e59d17ab6bf5650f0107c667b2a845de102bcf76675e7b9ba0f71c197a67fd90904ee04e58780971845869ffde0a7b9d828938e4f1def9c1be2a72943d9219775a0aee248dda1fb1de05ffa8749f753caefa9dce44e8321fb1a6bda759b7d0df5e2a556a8f7e0bd57cc8e7b6ab98a038fe291234d8864ee99c5ded05ffd34ff0d5fcfcc985623f0788659832d4e866306dea99fc9a247ef2b819ca99b06c477de2c5f913854b3978fdfc820646158872c0ef4b2cb1a1fcb60b34daa6677069f3e8603097207f54ac8d7adaa492bd067d6f48b084644cdfa279e9b39c90331d4ecfa7ded142664339aa9b44950e7aaa5a691153bab3acf548c86b4ccefd21fe58927f95df6c0fef31fa9a6719064444725af6ee603b1b6784bef4d1b7b8ea4867b334e7b08a61866a0a675263ad2874416dc867be42499d071d1b4a17676769ab23ac01357167bb2965fb6bf7f0611760f660d053621dbe1a7c92f7381ac323a0df5a00841a88a1804194b0ec93714a6437f03ece7b3a7723725e809d05da7bbfaf2e92cd65dae20878f3eda0f2da0a718f3cbeba099bceed0b6ab5cbe7ef5f202acc6644bdd795a97a2d7365857d2bd822594d9485409d04406ea5fed23cb7634ed1d132702bc84244af9b4d7c05e8532920742991dc65ad4ec56f52c77ad540e6e06402518e4500c5b352a4b59a375c6b72555f88f8a49a116f64e518e5c1f7bd4ea1db62b04e3ad24260ed6f0cd1e2cd7b6052f6620c5d20031254c96feb880802abadd377e4b998c67f6175d16148f58c7f240b489f5bc3dc6e8766f4041731daacf7133e5e35c21406a6204f149fe3979a60191a617ed462ee86a87f0637a78724adc6c664b2547c76638eadc3dd18c2e3eef51ebb6d433133b21192601c1a7efa1b2e5296f7497b7a3f336bc9e059b1d1e45e8144e8a5a4aa5c48f70eb817743b14f7589797201784df42f86ee0753e2fcca68b9b7aa3a0670398f1c435ad261727c5de503e4e1218a74b35d315a058e578a3ffe5a8446efd506cc8767c557affe7bbdac0f3fc620834cd708becbb2d3e9a87932b9554fa9bf6eb7206641afc0758d76a249112aa4639e9bbb32b936e1e65f955fc335059f0bdcc890ad1346c88eab5a6f9ae1e6227a12832dc976488a1c76a97645eb8e4e91b7b2c1f4f245c7ea145be4cd84ea0ff832cf916932e31a9b5a5f19bee487d7e30102121eacabccc4519107e809c269996ef10f632563e60fd06268aa56bc4371ba2dc3132308b3aad2b936fa26da5df9649aac7e2605b755b52b56a7aa590c16168233336ee228214d82cf0b1217b48efc54eb5ac1e303a6ef8ead7ecaac8875d5a0a44a09658da7eaae27b2599d67dccee697dfe3694a0f95e4cb6ac7180c448fa48270f02561d69cd4f62d946b879bba06877b0d816abaa3a5e0eb0a2db9e1cfb1fb8cec4c7172158dd1b649244a1fede6425f786369a6ad3f702b6b39d8685cb88177574f841a8ced376cb14f65019a7cfe030b772f7f7ca42985967eab3f9e7901418ea67f85749283c3d9a67186dca6073522d79ca23bb1c513723a5778151046621ba11e2fe6b2107e1e542cfbcc664cbc018516975d7a568115ece6fb88d20dd81a26d377fcb1c96c61ee67c2e9fc90685fe7a857663efa17b0f34a2dfd431d32e8e91eddb491b4b9a7d23af672e3f05e14a9d2a41e2b29ac6b37bacb54f314a903e311512edb98866d23624262e89367020e12adfdc606a14acfe25475be866f5886f31499f34d35036d929453941aacafdba7d0b56b39fb44d0208ce378367e3b8f63bb25dec0216026eae84bc0a89d785635362a7077ca36e8938b0cea352c95e533e73c6b774f43b6094e8fb27de16445b8ac26494f895341263b1c2808c6ee3225323bbc70a6de6af9debe0025661a8367ada54fd36578e646c19acab9a16f48131e8b39b27c10664de388d2363f7b2c55a9f678390f404215757d96744493cfd5422a28505610366606061014461039f60b17344c680f1e94678c5c7c5fdc32f572c7f975c440a6102d5f16772dcb7dcca65b2af67e92e19a51dc238fd1967e640a35195808c4f600c1b587f1c670dffc80df640490fbc8102682803d35a0f4d1d752f82912bd2ad7446c05361038e556771e76917ab0e1be26718ce167d6a153431027baee1831438f16872087d7864de37873d35750f43cf0239ddf2ebe9f06a09d621008dc783eb8e7cd06830eebeab3710baa26f7dc1be633ebcc861f94119ebb093966fc2e3fe5a011606f40fc9a79e799d057313de4928c6d20e22ec9620622ce8efee7240560174677055d6c8bde230bf86a518d79c01a9cbc50fce69946745d5d69a810680db60271d3267f34a33b009430372678a058706f563d3df166d8c67efe927773a52bb97686519aa64db7c252c9761672565ce3759e8a0db66938162c93be8c1773c772073ef95cb83afbfb47fa828fbc8252357cfde27b25261019279a2b64e1668b193c4aeab3497612af3a031a691c906f0952c9c0761ff0e6a53012df5c58f87a36377709867b6acc09155c40c81603a1b6f4ffd17aa916e847f66bbef3e87c72cc66961c126f552a273e9f9776f62f1778520dde50d56c2c73cbbfee2627855d588cce74aedac2783390850f0f3ae07e004bf468302d3ec60a877ffa45864301ebe48246ffe57ec6e2aedde622821a3648f8366c458db9594042c7319fb21695bbfe417b15b04b79a6ef08349c8c6ae7ed967a47f96588d94dbf842104eece15841b673c208154817e90d32a5046bb9745d99cf2f80171a0d76862ce8730c72bbde330b5cbf7c520c916938b6e048363c11ad2a63ef7a2befc261ce3429ee612e479c7a7781143e083c8e3057961b05870109994d34f1b571beb0d8667076c292a5d9f4587ea6397517851e2be0377c671f2c21269b0830eca952d7cc78c3a8d2deade0644182e75c8e85de4377dc000c46da1b5863e8e36446f95ec87177733c32f46524328e5b6102ce6101f36102703767991be4b356a6e83c67f79ceea8f8ededc4017971fef2aa9e0d76bb9dd64eab93be70bafc377e59090c8288d8447976c20a8a23e79498d1be86cae0e86b974bea75c1e14ee8739dbe77f7430707516e5ad258cee405577f7b139ad50ca9fe4942166151a1611d047cae2811dc8e0f37ee6ec9a3dd74447aea4f02ba10b8a6332a897d5d7ca663fdad799786647c7f171e52806701c459b0242d0b8567802476da4cd5348f1867d2b618dfd2d135b667e31e50fd99451f04057f2b3fcd5c18991117fe147953b093aab00fa49ee0ba203e0f6b0d9510f205204960051a67cf025f8812061076674566126dbce7a8140b7f8e3dd92a91d3960bbf62f098e6c76d0bcf283377b6239d6bf8073c5e6fd9fdfd61013555701c7e8f4e02e4078cfcce6f59b0b77fe00665aed6f9f3074763867b7baa608f71ab740e389327ad23bb08e54d744cf59064a0712c08702c7014b36bb04e695c78653710bea87bcb787cd507409b3b658a55eb1886a44f6fdb264c1ed3e77ded25d4e571f24e821c0cb7cb4cd9a8ca7c0fe10fb7ffa7731aad93adfa6482db48cfa7b2c33073c9dbbaf1c06c9693c249dd657f92fd41d31dd16572372130f75960b97d4958fae6e3c529bc06b13e0d51ae1d0d05266113a6799d3866d1f1bf867d6f3c7a3dd7eff0d833a313237ef8f3d8526286a19a76a91fd9133a627433f4826894c66f68b4696e428fbc069b7a7f3373e1bff6a1c013175bff0403af593337d272146beb4f60f8a69f4467daa37353d3a5914a67f5b5bca844e068ce19006672af55c0d67d3b6c5954c0d1fb27f42a028ed539fb613e3a66cd16a4a33ac4e27df585297f71bb1b82e950fc10183756ba50a98cd4ea40a8daa70bc2843d6477c1b9c807ca8b805d7a7d5a5f13a86e4b807845f74682ef726a267d1d38e2979ab80fd17571dad3337e5517f909303fd8d80e03befe244360f476bf22734a836bfea06140f576696598a3b0c75ddaccdfcc894167549c178609da505767435f58a9652db96c067d40e1414c35592cf1803445c1ef253ea60a9a697a733d255b6959612c51aab2437f3e915cf395155325371e6ce9832c0c70334f07065dd430a9efef942b31a486cf60135561020861017961038b3967182b8fd170d64f0467ad60fb11a78ddf90076f2f4b574af67cf909e6d2b71434179b826bab086398f62981eee0eb38567dbfeba881bcccea3f2e29d80bfac7288d1a1b5d134459a787beda605b0d6482756d37f97c05c5506d27c77062ad127ef7deabe4f60e786101606102926103e8f067f35a0102042e7d6067fa06b16bea68000d0766761656277465f2456bd0e4d636fc917393ae22032e7b52aeb6649805cad6d639836e8b8e0d933ab090b3695b22ba803b672f7740755e305fdcad5f415091a0aa04878ebc4be766ad9eb0cd731e08b41b47cb9f11868cddcec1f147e5958bb58669faa71471fcc01b7cfc49644abfb5972e6a5ead591ff5885eb928bc1c8667b23d15f14a18521a67ce257efb887823d80367de3b210b73c78353674b0cd504c0f3ad67043d610135602e61022b6102db6103457357b76c867e0da2a4a66e4ba8a9f7da7499685f2561020ff167828be3e6307e595967837e5e6609f2a8b90100b16cad033d0cd33fd7015b1cea07eb417ea1f0db7c15174e15aee2a11ab0a1df44e51064fe92ad53b1c76ec5b7de95c7752913dc825687d2c83c0df6683923f9bf0fe984b9624564e226ef86d26a7a312c352f93918b4474206b5a93abc0a0b30f60f20958b16f0fa8e914d0268497f2bc9a73226fcf1f71778f1583aac00d04c575a36ee906830665b16f9fbd9fc08e7c8e2545ff545da709d490635531317d736d5384b39a9f937f8d70190b8a89d71e13df3f586ed307e5966508d2ad178c1874ba484e624d3a3a73ae4b8c4b72c83586d0d48f900f0558485f31f9927c5d8491356576d37311cbe8a7a8465abf37bcb6f94b3f63ed1d93eba40a701e97d10c225550b315ca0bebd7c54a3ec36787e09280020b7c929d670b0f4efb272abdc167b4ae8f30c4ba6ffd04676806638ddb81ad7860291c602a356914c73b659e2f715376a2671d9d750ab81fda3a671dd611d15397c64901611df96090407841aa6846dca4fc41dc0964d548a62a83a733b420d7ccf3065173a6c8d06349e442ffc04dec944393c2b67a9a2a9b710f77223dd115c66317ae3a03ac79d1cd18e564869bc5589d64f4360d45c57b4ec97137a4ed9ab77f00d3d12d06bc494a93af559e8739c9eaa34c1f843a6759544ed9ab4ba551678931b23148eec0de18672821cbbc1a9d6e07607b61022967b4db7df3c9a0bbcef576bd2aafa84ae8e1e2431bdeb2eebd3e336033d6c702607561026a6101772060fd6102a361030ff0606860736103193e6101ac61014d6103cf73fd64fcdd6b9c80b392ea9a1547a5ed8fdcd3b97b3c3d7f3f18cb94f2fec122df42ff03d16bd251b9b8e2407ee3643affca883551612d8760081a326d78b31b30eb64d8f5b9394b008a396e2a6ed83a9ba57e42baac7f7bbd85436f3d7c4eeb4f8668ac37e9c4bec2f58ff164be7db2d248604c7900fa90e6726a99c2d6ad1b64e3f92b4e792650506c80b5e7f4d17efec9f37d9adb5691c2c0a0b3347c5d9930bcd5b2ee3c16cec54ec3bf8fb3cf78cc497adf26132fd218259dbc9aa4d4eac46f89b1990876058261f251631a16e397611c64779259a21800cb4679dcb0dfecf67290f6304118e866834d3a62be339c7abe1b93b19c5ee7de29ad8eb647348e093806192a075dc4682896328d610295610284206034403a67b1ad097315e68a36676fe8fc8763f98b3c0a67ca2f5a4f3ee2762a67b31f7b77251449fd1760ba6132725767ede9ef83992ce4b46713a601e8de1da78267ac1b25e563f7e6e008729eb0f73aac64236d352dc212984a7568840f8c70172b03a945fb28952a6d1df6a7a0187a947ac04a7afb9e4d7bfc04b50cebc25fab8483bd34efc3d660cb1bf04b7cc09ec8a18ddd4d12e79f64e0c075ec28dba7275873e194652c8e734a6c6408e7ef8ee378ea83b0f3280c238d89e751199274b058a67b0a9959ad0f9d3a6b4183f1641f0717231dc978db6c5d68c8d7b9996f6ce1b8ad954674d33d4b99488c78d8923d731663e2b6c3971366e3156118166ee71e939023ad0b94f1e38bdfafeffe616320798a20be3872cd7249be724b5d91e7e2ed9ccc7d54513b97a42e4f7a4c54544d857e57e08fd3439760a63e9ce4a662ea55f780487d4b999c67f418cab7829280b6600e1b6128a1566763dfe6e8fc2416f4679c6333032a0397990a674d9f5f4bbcf27dd067e2e826afd96eca851773667a90bc963d30859a2dd93ad903efe0100203eb3b365a679360277438218d7e60331d6103886103776101ec6102e673f733f4c5d47a5fdb5e6b083e6e678c300a71d97e6103cffa6102496102136103d46101146103ac73b7c1b35f845e38844e44649c253a403527150e916103d1f17fac711d4ad3df1c04050e58acdba5f1ee20b7b342ed1479e4829b000f0532b3937f0d1725c77c85bb76dc377508ba0c8c8a896d520fd0287cb8fe23a569370ca529601d1a60c04067994263770c671d506102a961030b6795252cbe00ed3a25f53862fa15165b7ee5996b6ce9283cbad0ac119a97d20544140c8e05f05e53b1c3342b135a30ed7ff0724358c483f38ee05c69ea93d1b58feabca92c0022719d47f1fb4d96363890610372557391d0aba42028813bfd8cda56bb1ba30d211945923f67f877f965b3845f76670c389f89b69cbca11860bb612b95575b71f9089e2a2562650385efe7673d37a72500d97dddf5b056bbf8dffe95e094763e3ad994f3d6ba7886a749f487c980bcac5b6fe4a3e46cf91561a2bd1079199dd7537a7e5cc6a10256cfbf9321838a0dfdbe6ec37520667547b9e6487efa552262777575f3ca2370865ea81931dd75adfb415f3e86ce6a715a5067f33379499b0bc99b601161d777966723a5d6e3cbc2b717602e1c7f8e9bd20e87defb783208e9db9a214140b7021c83f701d4b339a9d5a39ab7d1e960071a6102035176fd2c0005d0bd93da992726f0ed74cc73a0f39ee48c734d60f66f7c3ce2512831a6d0e0ef18cd4cc4ccb876f2b6170bdb1e68d2ee2d5da4955867a9946c18f081046e610808616c2576605c69fcc94ea668c600a04d7e50d9bf3daa705cba626263c51f64cb744f95e26fdd5d0a35f628d15bd62f0c4a26f22e69466172dc720a2e2773773c69ceeff379e30f6beaf6c1cdcd9967cbd7bdfc36d39adb6788e92f1a2091666a0367157e9fa828f12a5767e35bfcf73ad69e8b036f76b638975e76df44e6d70536c59d6e3474a4b9f4140b7470e136138d29fc1692f81b5caae7c661028160e4fd7f08c2d0c4039579aaffb435de2ed007e0dcac36beed12794702875ab0d29d88046c35c9398523d4dc63c87f0863a66f095dd018733efe55b030779f4836d5c96a3e3e35a5c5dd8a8359ac4d63adb4d678716f2c91f632a127c98f6540b4916880b337c079f41588254f936ed489b81557b592670d048379e9c1a2d18febdc66d2653346c9ad8479db1cc4a1542ad7ec8fee4951ced93cc81f2219dbfc6c8f76c1c6632f1453ff7ac2a80f3c1a16f8b337d154a71e2cba292404c24f6821cbfd3273bc753bdad1dbdb5de1a5e3fa0a94d0a9118bd405bb3b4c135b7b01926ca4f20ff44fa2d9cea8a1b083b997ae228edb3afc72535980359960c161348157676ad03fc0bfa9c3f6679afa2892e8b78c4a057b205748e4fb504ebd13883e6b63e32e27ad132db094828147d2f024666ed68c65cd91a5ddcdfc2a050a7d30e364f3e0c9087d7b2860b9fc10ff067971923e67de2cd93b5d3cd48d12ff331d58cef5a17076c42a349e82cb5c12367569b371dda7e579c1f05602f7d6f3e8888f82776468c8f623d57c761ead3f24d62979c58e02943efc8cb3ee43eebaa8a20723e562c3b8714658bb34ef6641efe2e47bf4c56d3e8dd47a8ba93670e7d0e362c22561b53c89457a250824f29639c0800f0168b23d303f3fe23be30daf7fb3345537266e83c0d53b02e1ac21d2641fd6c29a6461989b753bb4cf2c6d918262883968b7964f862179f9215ff10f78e94d4a9c94ea064f8d6a8d7bab80e58561282eaef10933f570631c01f01f61755a796f3a7e5970520fb2e3733b15a9b1dfbf7dea7e5fa23381e6e79c9664d1d716e0336600b2340a5b653f6591995bac69286fec4da5491227e183d8227b08046bd28d68f95b7d8d67cc6b949f62195b755b7447a77b76a1d9547571e287ae7924e981fc43ac49c27451073dfef18fe0e3e75eae01fd0e75b3117a5364706ff08d369ac87dd690010a0546f1ed2b007a32c16fb98a73b342b358ad5a0e550ee85e82fa20a0e023dbc10af36a7b79b0107d6709b0ec2a9d73b461fd2288c50e36194b959b19208282cc6d1b597aa916779dad564d2b877ef46e8731eccf4dc587b6d20dd63a0194f968790d80d783d4524f8b9c7fb33b06c2756340b20234b44470da00e1738d8b217974b98d12f1f1e8152458f5600f1a7302225a7680956b6882e4a7fb3af1bff52ac9def36f844f53b47e27ae420d8e9609cee49bc79067820d6689c769a4b3664d061916a7b01b67d74697413a203911093660846101ec610252f03a679a0d822b4e0afbea6795a5809fe3965f700b72b276215f5bffba7f97eed50af2b1c388333a45675b1de29399226f2c67a4d2309c2f2a3df2027d0085c1a7dc99a675479ab7628abf404fd1486c5c09a1459918243c888515757a21c6c97668a56c9aa48546a027e1191ca290b6d3976fd22fec4a5c5838cd6feb4237386d47b17e79be3d49bd9d71cb38a530a234ae162fa83a386ccee1cfc5ff023120b08b0777b2bd1a60285ffa06226441e35adac447b9380e6fa94f81f861ebff69fa9132c73a656b588b7995610b1f567ec981c0b26039bbf1da07fd7b397c9d8d31278d5f8d8aae14055e3191382333619f746dae2f9ce3a8ae7e0f8f2c827fa3006e67b6e224fccdc05f3ee4e8702a44677a4a60796dee1eed52f5a74e440b42587446e8276886b6be2c4809c16305673b166879b0eb06778ec8688e707a68021d6da2d9def8c7191c18f257b4ec7dd32f086868bd38e6a3dd8365b01b89dab4cb0661a7ca7a9072375aa530cb886d4d974409af6ee75e7a35b0ae762f7aeb4e6c86ebc614ed70c5532d0f3aaea15b88f96b223de4c90d889f7f8e09a8b48f3c2a9b73b92c1c3b2020a986ee720323cf2c4388a21c3ea28c543461014c52634cc08b4673940763c21f89657ed924456f33b39af9cd78cd586e44f881b81b357fc4eb7948e3af2a276fbe8a1492a264a3ced67c42bfbecea0aa665555b9ca2bad69640308d1f94e6271c07a792848a5a9738bb4ee74d5952a6824dc5ea8334c3642667f97e26e7aed4fbadaea4af5b72149b5f54d98727ebfa20e6ba472b708366fb868308dc3ce68a860d8ef66176f77f8a522aa8967a2074ea62c2e8b0e6768c6610bc64898e30a763ae4e443b0643ae5a6d6077ac6630522d6cdd53d10c7e74267d6bfa6aeac18d787602f1c6af2c0f9b9647c84ec18f4f97d7fcc69bc01a8f09de4b7a95314172c16dd6f29ce2778e4f274c1f7e6d2d97e4aad510f57b29145aa6fa8768c73c1fb41a6b3022e43ebbdbafbca26caa08a67509c05907039e8236521be5d40f0ff64ad6bf59a156c5766beabaec82d6a14cfb3e9ab610e59633fc74d177670c23269ac397a71358e735588439ea4d60da566a512a176cb0e28c309388a230b3c21fef2816a75c180712dea3b8061b9636f16a4cedfcd9b3bd486afd024ff99869c68bdddca0c5c2e78e3e275650ac57c8f8763c5a52d7b15ef98a844e8c5099351ad787a0a888bfecf1817412ebbce39e9d24bde24e3f2ac0af812ec68109cb50c2754cf0ec99f7b92591ee106ef29f2650362d649caf8b820174be6c4833d04fe65e6826598b33aa06be7660fb0602af204ec610db46beae9600759e2ce9472f20960692bfafb09bb4e611a065e6825fb657bf78a8f5b1770b44c7d2d96831f22cc1e015e5b3f8466ad6ef137bf7081d89642eaaeae9449f4c160286816bac7d087ed999f406b6beee8a95ae25cb13d1527e86a3ada1233e1d019f5874c4e615ce89c3a67577bd024db802cae5b67f9762a8399c12153186fb942de0f346492249f029160b57490d377b3756c5e8a2bca941cb1ab308cacda89af3f7e3d1095344661463b6dacbeacbd9d3e01161889428791687ef30c0fe6bf0e3a14786784df8f0dc5f164a1922d49ede13b017b0d53b777d284677622e3fd7fce35186778a688bc5409e8d2675cd2b9df48a70ead6103ef6101a3a367cf942fe4e91799a067ecb0b9ea3eb40d38067bc8b7124cecc11f8431b817d172c243afdf09de1db756429c745171e35a67169a40decf79c642670f0fba54ef085925077acc0cbaeaab311e1a02828c2fc5a3aa815ce370de65e2867c939657387cd6753bd37e2f0695f209e140a43faaee65ee3b58c717ec7cc98ceab4bd780f5815e7a99cb0dc15d1cb6f21a9c7c0162bdd83189e896c75906dd67db1afc485e197278b1170aebc70c90e0953c67d975c4c47da2ae782f9518b658a6470fed3a463cd4699f260dd7c3bf900a983d94bf82291ba4661e702e2765ea85eef806cdfa312b6483f7eb3154cc938c7490d3ac981498e9af4d8ed7a751ba36430129a9ae89d48f4c97bdde11e328285fd93ba1226ade98935285825481c6666eb4820dbc01361206568059992df4812187d34987c5c9b882f5238531639ff0b18820ee89b1770bf73ae985236c497acf58243612d3c565061036c61034c61027a60e26103667365a31b07e2e5da6e8d3864248788ff5466ce1453610339f260085b7cd2c327cb5c3853bf63bf459947c24992b60852ed0ee16b7794cc5d9d8e76be8102e52b265167d1a18d6f0cb092f87d63df3dc789f5739e13bc4d6fd723dda5fb5f6c0653f39afa10ef3174b7bf65eebffb7b155f6fe63cc3c21417fd021557116ae751592c37a10d579bf99a7c6919853bb112a18b893b491c72ae066539858014e5c271a8f7b2abde7e64efc2f118d065b1251c9781fe6a2f5991e630b04e556dd31c78858e30d9cc880573e4e05b341ef30c5798867cfc20e50656cf7800894b97faebe39b80a88b1429d35067fe3a2b0444a94aa5897764c230ebbca03f64d5a74d341ebfb45c9a6534cfe555b4766b52d9c0098baaf4ba8aaea53a738a0c118bc09a9804349998316157e782ddc9e2dc79fde5a401a9af5349110a760782c169bd2c5b80eafcb916c8789d7ab8b029ea912561ce5ddcbc24fe5b6279ea888624180072101828988f67b8b6561a11c195e9678429bd78ae2243590664e4ba37f20461f1ae77bf828c4a28ddedfbb036b67bb2bf4c2eb9011aa3c7713bde65e25bdba7a3047c9ed5deda434eb32bc9d38fc149b70a68e5b0f9aa9245221a2bc1fb4efa718ded9f7ed258247c51821a951938b27d803561ebd27464dafc1718152219ff68a2ff21a122d3a259ed6d986112c27e9d4d036ae4445c3e592c4f89e4c8084aa18c71914a7e2382a47716381f9c74896767f5390d7ae2f5e567e1065ac24473f973678c422e2f04a50bbb0867e8e9d79800e54a2561012c61027aa1673ec07377b93234df672924870e3a5792d10167eccd73d4dc83d0f267825df6b4563160890b672275d522c101e69d675b172aea3b90c5c267477e28d241a330280967454871c54fd038a967422cc61a6e7727250a6103855460f060fb6101417322d3e1d775f6960684042d549f2a7b0201e93d943c434367e1321272f877b151677c18316222fe5ae6167f28066f4297ea279c6911a56fecf804680f849930b9b8f480a368309a5e37e38a61012455306103576101926103857300aa643e105cbd01f0c3cebcd0c3eed8fc1fccf23c5b437db59c4e2ff415452cb92756bdf08529fc5a3f1e77461f7a94a5e5724dd19261938064336e2e889d750101ee2400069778cc6343bcc055466eb54192e34eaf78903fe4b279a3f5cdf2291b307c88dc826ec21e90178b62f52a71b862e43b00d911948a09b5b4a95470b2dfa366e0355a822790e07da0a1eb2a911e161821a1abec352c539b03d7a0e60a7394341de262e2c8947c8bc760d28d1c113ce3176f12c4a8aef1c9426aaa7e51a061b1ad71810064c6bbb4e6437adbe54f1a0101b0073a100b07a0fc1443326e7eb379252152d0ade06b275296ee1d96afdecce071d8609b630e0a7c2e9c7a1627e669739c88ac02bb80947c560ad516b2b1e8afdf14810de47b789aaa1340ffc76caf54a05e1d8fe759dca55e8abe792beb92c762e3a1446977f1fbe6beda16b8aa2c76a822e6a31f65f245ee52843054f1b387266d88664c4aa177793bc683a76038017326c546af41d349019921de638ea5506a7f017ef721a991ff3b60509567128a621e11be205d67b432edefef91ef6a076101ff606b6101b0f0634a62f0b0699b152d268860c34b592679262617914ba0a7722f136ee021d9a57653985681e709e5d6672165b4f342a50c166e729da6e0909f9d8c710d6c94c25055623293e663dc3b30d36759bc91de6a8bd3dd6e9c69b4e518092a013f79777b44b4d39760aa67aad824c8dacb45bf674502e2e4646e1b1a67a971ba9a1dadaf0b0867877c9a0d7583c48d6799f3289f7b5c726607610377546f6fef264bbc443e5202b4fc8c26cc91d260f7664d7e45dfcd37da742821af9f2223968de5ca1c4726bf355c4c8c0d4c3e63f1b47f7b620651fb6c464b05d2dc5917da1d57aaa3b86d425f81bef3a76fae6344138891507deab6a23b703f10c48169b8a5f51ae3c1310f5bc341b819026ce540b03a996fdca8adeea8798b95c2ee6b7e3c463be873bf5989b80c9479b1375fa3b558faeadc91e148fa650db5c97ae57678b639791fd4360fd6d14f6f72d1730cd0ea2d22812015537a207a08c52c65313a61005ee45dbc8fa6188abdc2c8c400873d32d6744e6ee6ae47e0d2c3c0127dcfdc689475ed72a75a84813b2eb7d939a0353aa1b0635e1b07f3622334e19f7cb0ca4013552b70da758cad3f322cae6b444cc91abb04db8348c68ad4538067c73deb0db33b4bb967a49477dcfb9ed5be0462408df875bb934b7c5dee9e72b8f1ef78943424da8e8aacbb1a0d6102e2610238fd74e61173d56c5d951756a9e7718893538aee1f17c99475ed8ba0d80c1638ede1394fc38ef6350b1864109ba3826e83674a154e97ddeb8e5ef8804ffd166377f256137d0a71150e658b9d33b457d9d21146fdebc650af01998844f1470127fe3e067df80e006e36ecafd43bfa51ea4620a64d0ba539e2a8ba65866c51a5444e517bdfc29845685d59785653b1a26308f1fc7051286ec0179fdd2fe776cc6ff4c1f87f8ae191fbfa61ebd089555b246c2af34c4136a64b332a163efff863989a8c247cfbc10be0efed675bf8631e3fd72eb6e77b5bec6dcc7a3a7e75d6a24a417daa95b8becdad6ad7718cdfa0b68de85b0456391f968a1d5559240bd1c50a9a6ca980250b62ad9f3b796236071b6dca1fe004492bf5923a2923e26ed87c3bc8ac4c618bcf75a3941d056386f6647725c0f7675ac8f89833cf625e7811de8a48d3d45087b8761c72b626b3826c4d235380cd85d65c7b4e18eec0d181679e41d57886a1bdf84027b8b4fdd801d442d67023917c44854c4cf47f3396cc139918eb74caef20a76a63cf1d653959323bba2d6864e89129a207a9e07d6062947c9fd6aaeb884e90c4c94fd7ebfaad2ee6145e8e8d35ebdcaaea5da6fecf675ee1925fecca75cf674ae34ba5f2ef972e0360066101426103bc61010f73ff750b991b0a9bca997ee1a0bfbceb79fa150bd6610307f467d6badbba468853a160141d7c07694329893564cc60a489dfcf9bff812e9823eddd2bba0c43038a660b67c45601ce84537ba267c30089d1b2a2a3b8167a638b4225f6c5a2e079ef1d59a374ad372be1c77a4cb35daf3dfe7f7ec26880bf7ef4108c97e40b33d64040b0237ffaa467a4d4f926d3cffe6121eb66368da3a899b0e26fd5eff5662a787c7f3e02c34946c256076653fa06ef990f4d6e65a41814cc92310d3c9403afed9f166d222101a26bcf9144d13ee97b1cf861dc1c7921c85248856f301a22e1799b68cc5dea99b41bc0448270b2b4886dad57b1e0e439f4874a1341a3b80667b47874c62914e4fd676d51b809beec2ac463fca7d8fd9b7b9c177e695799f73a9e7d478d36351b05bf25fede3a54ba0cd7a71f1a60706c7da91a01ca2b6f71da335a5af97af42669df34fef57d8a74153444f15b6e619a671cc2f3807c002dd772d73f796843b0826e05d56f42011a62050de1c36635f21956fccae67bcdeb7d9d362468117c9d89c66c41d714bf6270d5b03877ff555afcb76d79ad95220697fdfbb9c50feb056f6e3bb39bd4aa0efea86c8f6b77d931a17ce87ff77459c9f721325661ab6595c30de1befdc3f9b08089c8c4bc5ab76460f44e0b0b8a3361028e61020afd67e2ec22c0258b15a67bf535144d0c20579553691b101c4a1995ed5d5c387e473b51a4c03d507676591edc548903f21a363bb0b1d029c41f08e987db637c6dbe4ac4b3c74bb8f8fed7bebe6c107d03a263cc7f56bc2429a5664e959070f64f45c3de3e666da51167a7b13c916883877161d92b6c0815761d1752f76c5da39ec0afabdbcf120e00d0fe3d282c6129616b527e2a00b7e20cd1d96f062a47e9ecdb8f6aaa410e12ea0638dc3d525c2fc7a035956739caaf921c25601f67aa31a065521c69b80561030f6102cff3671208ad40a10e0801676ea9708e28f3b6dd0a6745b3bf86111535a960171c72c064b71a90b2dd4c721f39357802b161b1a85674b5e0b827bcc73121005071cb4093e2a3b04a32ed5e7d25b9e0bfca030948a8dfe738d9403aa480ef68edbddda4c4147696d87df064603b4c45857de262398d7a3acf920b9c1f09b7bb2010e3dbd94a26d21750f4ee691b179e6ec2eb65af7d17423c2ae64c6f8bec6d7a3a4a141965293b5f52047d83c14191a541708c80f83cda61cdff1e6215cbc169e4e77776573656c24a0c76a0860d7a5f53147dd87a4313acb32670eeddf3425510fa67b74a7f31d98a5fd16d479323f01e19944d108213c8e863733a038ac657eb7467548de9ad9f63c4f2565cf50b6d434ae0fa4dcb1295f9eba00039fc9c6103546101f961039bf045763d1da7e6e3087fb76a95f3436512554952946ecd54e63e7039e487f405495d235ef2fa4fe931dbd34f7cfb5f772f4778593ee88d50ee6b98b3cbe9b48816e084a8a33249176407765e418f93b05fe0f461c45f934d2c6b656eca3d7e39d43469a24f178ce4dbc36b94557e9f4865f97751c885ab73a099c3b392615591b40b38b930c5abe10a172e348d6c22c38e68a94ec1f3870552ceb978bd101db8d2b49acfb14b1c8fb6d1c668f416f31be9365076ef966718ea6c2493b3ecf567068b615364bfc1371861027d60626103b273487ad47bff98b9312710063b2f6e1ffc6bee8c5c3c678639ecabd98c799167a893e0280b0b6742670de6d5478517c49709734aeaa0e9b77a354817ade48ac29967152189833fff5b61015061012061023761014473924a92ee74c9bc49bcaebdacb45fb08ae6fc2c27610243f4670b42b65ee6cab9c3673d34b9a6a2b1745267956209020031afd008610317604860fb39b16f0c177f73088c6d0166cc14c95f1bdb56750be2a8c6f601e892dbae99604fa43d2c7795c6839b80817760344eece8d0e6f8b59ca462c08312e8ae62bfa7fce0aad4614ecd7ed0628814d9df5d9549b9f456f57ab80c91edd6730164628748d677eb12ff146a3e6a9b8bb747a7033aab117ba982a4799cd38aaa664c884f0fa72a8ed35db92689d930c6a3227c0c762f1b376bd6baadea228929197c251e1b9d71bc93248190667a332e058bddb872d32ee3d0b718e6140f202b268d76c0f588fa34660b3ede137b32186339b696e771d06e04b9283ed310e70eabba5291926a147a67edd410fd6126af087333c37223ce2adb1adc230fe74ef0a0b61a1abec178308dce7aac155376cff6c074f8bdf1d6069317cd7cb28d9ad87e4f8f8eb63ebd918185406600eb08559a70e734b1eb5a7d3effaea72de3a949683a60874eeceaa32d6a61ba6a9f77cf22ba72008147d0edb4933b2295f5dd281cd3b7763248c862df5f4b6ac328eb11d23c14bfc13aaf735f0a2ffb083615510d9c73977d72d6d0bc991a58610f2f8462e21dbd6c1da9191f7a15b3fe32eaf2475e79444e54c5f8c8525e53afe97dced524bfc3369669282f6d56ed15679dfa39d9001ccb1a7506527810ae4f5f4c151c9708ad3395713157bfd93bd8651c16e9d156d864a43724d8bd756bf8ce5d29928c525135a8fb59c0d405407b6417c954664fcf853b36376c7d4824dfa552659b8ff8b3d57e617c8f92eec109f922a6286f22a3cb25423667b9eededcd2a5a92577b0069295faa3c33dde765c9f34ecb0ef29d85482744d873963a561e47b620344b09b610174600d6103673e67d2e8d574c250186960161b608e72488093b9f04ca8fa7a0de8865b483ef1c4f6cd61f55f7e4513a4d28f54c2a96e1d43a4c4a9bd42fd03d25955937da62af45da9125c19730a803bf48bbda24e5360e50ba9b4a461201abf0b7e6f5dceae071c0f08cc66c969316ae09fe756bfbed4568d8183bfdce62d28e17344b14edbf2dc68946d236015b8f12eaf2f67c1c161d3956784e8d883edec81436a747c90fed5cc47c95c48f078897247e86cee53a88e10fa2229c4c70a25cde12316c95be1117c0fa77980e68f25052bf331a591131ea3caeb213b3a04102e3c7c8753e57cc26eabf16869a692cd4d019963163cc0192083de701cdf7e6c6918b67569b32238215bfcee4171b39c7388103133cd3a488c7861ef32e58778bc84799b4fff6e87f75259d225b1bd16e0372d4f3ee961015d61027a61022060e0739669a6b7eda4b9eef1ac3ae7c1751e82f4a26fdd61010afa3667fa1f958a772a688567abfb347df36efad10466ed10de2021279c75a57d3f8411e71b6ffcfd110eb9cc60d69a6400e7bdb062f78706657bfcf921a7a871c5ab3b181a6c721c55214a748f2534f43c1d73cd1c37fdbd2a52975263680c7aa763ef97d4d72e71f391970b3611445468935608fa0e8be2ad186ece1f40726d5e4583629ebb9af6ea926f2bd8b2fbd9c556ecf74b99e79ddfc8e170826af1dbcbde083c47240ae2914ec646ff7020e9b7ed42df9fb5070b4314794827acc478ac8c5c95a3596dfe9574507bd3cf03df159dc7bb65fbad42926fd248a00f15ab2a615b3305e53a32d30b8c6760f92eee10633ae9674235bf261896cbd5175b67a0b0530ad8ed0a8467d9a06aec83ff8a8d0a65deef34823bb03a3d67e00abc54a5eb261f67a90dda6738c362c3046e6d75da584ac4d29d2252f78750db6861039b54679495f2ad1316f22d674eb700b2cb6f256b037c4444a7865ec290c34d8a500b95d13497f814ceeb7a216f7f1fc5c22063751f304eea4d8e5bd3901b81ae8e4b58ac11205a0d52246a8cdc31713ebc93d90384157e410ee41ff1b7bad07746b2d116edd5f98ead489a7b12141b697c6a3a43a2536bbc923c341ff54e4239f421fd6ae0128e1fd946690d84926d7c6ee7b725a75acf95c8fa138e47e665845fdf566ac33357a1e23ef5021d863a6f1cde104f9fbc16e8597de033f78b457279586b7e1bcab48e48f75304ae6dd06d81b8eb78bd5fd9b8c590106b1bdb3fb5728c5f95ad4eb476916d9575b13f35dd86c0e5fe060579a469a37afba35e1c69755b09646ee26c339b6403fa4ad4d666320a5065ebd7197491655aa62e139dcf9178ecca57b356756c8abd136e7e4ee22ee493d2981510c8823f909195d2c960e7a5620467950c48cdc0b59ba4636ff5c2c0754f92bcb3546a33c077fff4ad7112a226d16c1fb6930f7befeaecf54ad27766072297790e49254d1322c6256b8d6daa44ba3a82724b0ec60c25ad14af1ae6a025a01380109459bc7a342cf204932246cf2f8e5bba4a748eb9eb6799de10a5d85908bd3d652ffd42a26a3872e9317875211a9db06f2b658d37d8e0ef37ab629c7dc14041231ef6c429818f71c142ab17cefb9f79802cb50f726446ca2c252b7e950a99ea364337fe7a89b552bbf21f72fe356189d22bb59477e24f5d30fca961ff106dbd3bca6b51349226029f47357dec7d314665cffc8a9d673682f0e9b114f8e29517244e0b243514019531be470775dbb0c07116d798b94908dfbcc30c460c8061ca4aad536318618f2d7b4ff1b79633a40c78581ec85836fc9037a786b6c6c4a898d5350add827559ec6b39ee8f88b367afd4372b737344363ae4eabee07b218fcad5014304df9a2ece1c6f16d2edfdfce17388fc2bb82e12b04c6a66577a3e1610bd4fa777906941f80d9bde1cb93811e5750bb0073e29d0a3f0626c086e70a9cd6b35d0bf8696f19b679dd34faec800cc546701e16843cb3e75a41967dec297140e0a0e5467b4522c7e67b7485367509207012368dfc60969a60ec3f95c84fda1019d61035f6101ac61017b60e861032173bc49e3abcb9e896cfa5153864f78ba05e80d5892610356f16b94c48d3fe8e598bb4dea7d7867ec8ad7efc81ece35677d104d8ba6afdf14668b307bd02603d2096770afcc17bf02129d67c42cffb6c509365f02671dacaacb50e677cf6786f94bbf50b7348904608261016261030d610309603a737f311661233bf9cec4cf638509b01b5d9cd9c7d2603df273a8476b7e410fa28e48b2bd7d33af7409d5fa8fc5316751357f28c1dbbc4b675c909094ec1cef6f047fa0527252e40f5a014d43909931d19a619afb981ab3baae416ff3e14ca0674fdb61039a52584563774d1c4b67e1cce0630f5eb966674670800e891894a50a67bc2484cb37ba3203601a1b6101b76101df61023cf06103b160b16103baf0386ffa16c26d6e90c8d67951b9bf7c545fb6675f388c4f5ce4ab1567f629bae0642cb66c0a3650752c46dc54c64843c32604949cbf3ab3de9bec4be758c87ae5e99a5715dabbdb5736c82243b2dd38d56e0002bb1bdc5d70858d724a0f22e40116364fc38d25b2707105b78f1ea7783b1cd7ff852b030ef00facadd23d8a5c3ddd82ae8477bd2e2e6d29f87ebf5d9078858880e9705c727a3f3c30fa684e2d7a4c03c79b935f2dc80c4116b36e7f3a4274fe6c714941b10ab2153044760139059d53aef8062c65f35edbb56c818767bb02c99d2a2958ac67ad60b1ff0eb1ac800a67da674fe12a527c18675430ce3897500ffc0b67f6d3968b2b65284167819d037ac849e5af67ba277ea7a2cde50a09610223546878b77912c82decb53a798768d167ab43f3a9660845db9d6a6b4af0402f25672ca97008f461aa976dfbd3804bb6ff90ab30970b6de6e56570e195cb44cc78c92cda049d7d558687fcb6be5de81adebfce7089d4e6e69e317220d3efb2b2363ff32e8d1e4e07e81486c111226dc7bab9746033cece43b01cdf8a147529bb297ba2c1258fad28bf871ad155d1a60c686d761c753cc1fe2ba522a622c040c8820feaaf45007cd3906a34791e881dcdbf8add0b41c8b99cb1a24fec46f33fe60cad9345ff6f61c26c7e4150bf706e29f1e2bee971ef6638a00db98c0c7e77534b6234195b6f8389368c67dac67b2d6e9c4ee767b8125c658c299d7c036785564e0314cedfe067a664c4a6b5c47e5e067206e3aadee34959091c42d427378b6c9a5eeb7477ce50a48dad42699b82c71a55466e9b4d3ac937636b473c75755ce7babb337709795538c53ad3f5563fc39d6e0bbd5d620d478f66d3c1af80425e6b7b6ce670a40b99d4072090ae80fe1847e55a528d446e1ce471ab74095c7a7ead9cc5179f710429be2babb7f605a36962fcfe9d2156e9db73446ec809bf8feb66f571728eb4956cce737473c649a54b365c5f3228bcdbdc61bf87c72aacaf846c6eeb5ddf6eaf85f138d4be0080689a47f4f4ce542c360570be436bb195d150bf91b75205dfb67ddecb9a67d55009b363a624c260351b6ebc8348fe49a091a4dc1785b26a03e078b380ee258661e58ccc00c433b9fa3187256f84a994a730e7567b82456213f6f06d3bc997169903e53ccab3a73ad070a2eac8722efe40813a610353606661012d6102f2603d73f3c26221873eabb0dfd20dc35a089c14c14e075a6103bdf27d31c155d0a2e1cdc0950e955bb2bef430df8310333f27754417d60e2fca817d1a72e9c391efb22db4b45f37d6ec854fe5c4a781ea692594ca38d4a094536e44e8284879af109ae9509c0676e8b17b38892d682953e1f28bcc67d74fa975de42e216df7df23738dd35c3f96cbb7b2af9008fdb18acf54919c1736e5141d6061d84f07b46a3e970fe52c6b1650d677589e3bccd7f38ad4b10a80112bdb43bf207fe0efe388264e81465b84962043e3e67c9e95c201be1666e75b9d21cdb3030bb21ac00069c81d6f8daedbece6119208a67ceb4f07d06d0bf0e60171c6092610317537f03bbce58a053d36d83c32e64fdac3cdb3c5537c84bd02b003f75c32cb2558211601e1a72f27c98afe0be83578334b1b2d3678e9c59dc010067dddeb7d0dd511ff86706a41f4d3c69a6be0a67e61191ee9e1e6a8e67d6fd2261ce15d15018682b2bfdbd152f90aca2666af72b84393b377d153643c6060b07ddbc0755488352e7c52c95eb8850c79fe99bf9241f12af63286989ff61c5a77c30c89c9948171b7b86bc58c760c6ca09ff7d9580cd11719eb65687742e7a68d9051e9a1d7bb48e28609e8d4b3b4c98319c30d0c6a8b61fcf206b7e3c02fe934383190a1808596cf2e1c6d97af4f1c78e90139ffd6cd6273ee4ef17f8bbec058fbab987610243610342f37f29201b6bb7e3f3ca65845565bde6951d7462e1821c43967e78d3b195840f88cc601b1a67413dbb9d0234290b60041d6591f4d2b5a7b073ca1fb082534b4b80ce1e5b32e421856da2d8f2d77bb090aee439f570d905b4bad657fe283c260d31a2754cdf13f9e87b8c6492ddf6f63061f51e604893606c6039610365738cf47a4a716d6cadfe7d7b192f39b73de0f7519f3c67f4aa5c312ac39a0b67ca788c522820c27b0b7a609408408937d1d920dbfa55fcf2051a101a1f951423b8aef50e3f4561017d610339fd67ada857689165989267fb77f845986eee64017fe5dc8c3b2c1387678b8ad7c7247ab8dc78499bb00191e392f994675b72f5126b67779f518bab85903a67f35744a4f91506c1196586dff6a69e564266e11f00ab813b50658ded5b1f8d3364ee2e74957b619405792d4adc30714c6c48dcc02f7069a962f2a204c1fc2b0ccc05d6c4703ea1f2e4eea45bfdcc94efcc65240c25a56dcd99a877cc452bf0cf1a4a2e445f7c01941c215f662785b28a51ee3e4865be20a2418d0609f3189be63ea778623b0747612f58896613c52e20d3ab886e863c5a4e3cee05c008c669c9beef326e09966e62d4b180564ac545a08a06cc7b627101db12b8f4907fd406f926218813ed449ffc5d276412a170f1647c47d41c6ef99ef01b99cc248ee1325aac61f9bb43594af2937431639ef5926718db7d74df391fcc671d403a1ebc09301d0b304467d0c9bb27d9dfdf4d678bc6ce29fed4c22d67f39ad7d059cc3ea10961018651673ecd008b874f33be677ee66212d5ffb43967e1b383b662e3e3ed086101b1601f6062393461fe5161757e7183d837c8b5782070c99f3bea65d2c0b4ade76e017c3c34c6e9a603f469ce66a21db3613a807bb8e884bc4a347ba40a6a44cb6c0eb7494e75f8b1881dd9eaf9433e4d6b151bdeaa07edc4c395432e946b213b144378d6db73573348867bf9204659f95001a9f2c0b541c573e75f90f3e68b7647ec4bdfd2dbd672d1ef29597d3eee79269a653164f7561684eef8789cb3dbad8da7eef1b3dc6a1136e91b9bfdab7ed13db94d8976683ac8774d20a60ec9fd6fe9e9590a48d91e8e8969030af31169fa7886771ef58538d4d0e92174276a96448d2dd70f0d9ea82bd9708d676b7ad7de08f0a3da67a768e09c6f5a11e6176102cc54b2761b6dfc0cee67b79d583b993688ce154b110c530bc2e9e7678bb5b2c2fa44ac81677abd402d9c2b9820054267b1bf561bd555bfd46713a5841b78e3c9c767dace725e12805272097c5dd908800ab155ed9c6dabb2a6de455ba13e1cb1e4fa12159b05281a1f631366392765f6d5f715d7346d642bf5467518c88038e5adae452a713efdccdd218f260e864091153a29da25c7bb71f942220689fb8287b314dbf34c489538f3006a4fa67180cf531d49ebe345693305ccbad050381076a66522b71f166a6460db70c3f706c8d4d5f745dfb29533d286486d2060eb691270f51903b259ec16846fa3cfd69460dd523e2bcd19d3e437ee2074b355f019ddf86322221582e08f74446b099db0e4ee623f9b058f6297cd36679678e8813aa67dcd67b624ea7081172de6670bd969bdf4faf61709729dc544f628c79bd12317be8dcaabef55a678cf6b3ab39462bf0f62893069f34162e4b1a67138b8e7c6a544ddfbd1c0e186cae5d46f72656b90a3e58ecf47e3491f3229f77942933a4038286e92a56906326981d40c679b362d7323a043773b6a6c1d6440b1fa5a7a8995c3865b7441c04a800d2c52179430f286081d8de02947fbf85867f14dad8b188e581d6bc8235a55ab4e6d412e6cea6f6996b3a4568c425d8721877adba290f2b3fca8354b638ea8a3ea9f16a3f4bf9d7fa966750ca495693d183dfee84c1db5790f6fb01650cf4d580145a79cd1a7151be1e4654d60483fbe4b631f6fbf3f723f50dcf141031a55d5f0db10056dc274579ff3689146e0af9eb293e0457539a561edde783e869f99d55cbd3c5fa9a3928278bb639a6102426102616102b36103af735f0e4d96eecfd4b209f95825ab7e131684ff6b1d606ffa72c41edbdc076787abb06b94a868a4718586738961013c600afd6bb9e8135683f07e43f501817260c16504417d10366879984ebcc3d69f78df8128efcdfd2239b7d2812b18ee67f5590b3c7601762fbd2c95e538c11fbcc9c51df313a5358953a2746477e2ccd1533cf13481fd702b82388591bf23f829ff5bb12aaf75c113e4d858a72afb3bbaeeeaa85c614549744f1b5c45716863c33dd544b7800cf7e5d9729360e6579f74c0add949ce65b65a0688126edbca264812ae3c16e87dc6e76352dc52889863d1054e0eb6c5bba6e47c28524bcec127d5a8025d9775965116a84ce8ea0a362a4476078f839bdfd99445a1448a3067cfddea3b5ff1121a67cbfc9f68aaae4df317676edcd68d3fbb7b30677ceaaef51d1df99e173d69c20b012c01ca4a19eeba5b672dff246b484f1801671b3a8df1a5448bba166d60fb341b2484d16b232df09c214558673b43a10faebb278f67d206eb4f061382da67f1dfa96c75523da90867204a579e31df7f4e67fa65f3020277dc7f673fc268d7868c51986765dbe5e0f2115d326103e261011ba46ec66976d6ce513eb621155f87c1fe12673b8f001d24dcac316101ab61027367a6c6ed469c944563f56afe0fb9f8daff54c2d1410861c2bb61c53a62afc2807967d78171c168b0b30b53bdd0d34d38a770bd30d44a42599a1252615da9702256de606b9cd3b7f3d688a278d44436c360899661365c791514dcdff6ca3ea9b1e95d90ebdf201b6705756db69e85cf55d16c4b4b106f33b67f8ebecebe66827c05200240ced3db6082092c6439a947204b4644438b9e243868dc2cfa197818f58aefb9c298bb7e5e0e51062b9353aa054b567b8b94532b6266d671786dcd559a340ef1e878f7ee186b3c97cda6bf056fca2b8e9a1e69b6704bcb8f46bc5a77157bee4ea7fd6c29eec27fca04642ee66a9b4b3dca341b5d98dba868d6cb97672fd46c6db3aa0e04600b1c7aaeb8509416041443771dfb85e59da758ffdf81d2ebcab35cf1ee6c73effb2c6c8e7cc188cb71657a682166eeaa046f073b60eb4067570d73d3520cd56d67c100a3685ab053a1166756cb706e08620fab673a705d6f3e822a390367c657252ead96567c601a1d670750598445a0fc3c60181b67fa15691932ade7296786a76d567479ee820b6df2361c0e0bcf7f268acbec99186e6ed094b6f0b8b404e1396022ecaaacdf90672473b6132d0b2cb167e53a69e6e4f69abc066731fbbf83f9ea120767dda86b191b425c850a6718c1551bf1da2af0602b1d7ffa70aa2c1fa6a05100abb102bc732ed87fc8d8568ee591138d20990b428d2cc3608655603e6103c46102fe60f4610261738f8340da153ebe4b75e9289045f8c7c9bfeb85d26101c7f26720a20f079d9453c0676f0e37b96012043d04782177a5dd4f82614d2f1cc5ad4e9300bf54f84756edc8ad9b756d6a5b08438c39fa4c7d658ac6e8056300b74bf8670a4790456be894426132b574e2e43b219d3c9a20589da900e88ee4bc33a7009a07600b95417dbfcb6c5ee9c83b81843296fe5ef6af331a5533d41e5d8739311a8a3f26eb79db363af4163590a23fac87593f31abd3bfa183e038a8b7057b35631035e3bd7abb3ecded0b43a35732139329184bd119e4cf692473171b6e174a316768af559b9eea3cbc67f24f52549a0fc0cc7582c13725206124c814288134aaba144cbd755b1374d56431715f3c796ed0a643d482e488bbe8af7d7d949b4572f5064cf5459c0c41dbfb5fac09baaaa681710e797d0a32b310200ef9b6816f3df3bfd4d614c8be6581531528357178f8ce3041efb68df1746719f8e4b0dfd10501b26ffadf403850766fccecf023084b53bd5d75d8a4d80941d5551a29fc5ede66e64d6597554fdd8d73721f9b5714d4c0270f1fa128649685266dc59e1b72bb7e7c51edf763a7a12d439e5ae36d2e7956496194246d639bea36278b25d8549e91a27ae8636d92e2eb7ef52902be3bf6e95fc77b730b1bd58e7993d9ded52f1b651b843f32d97fb3a56af427a1ab094f3191d823ca867c365924586ff0715a2aedcab50c2cfc5a413a4ac5633f36dd5e2647b0f664367deb53d865b5572fa9e0c96349492d1a6965ea230a817c1daaee587ea83bda55d3f2a0bd05c55d57952c764a2950f85877025273213f327e6fa8cd67029476202ad927437ecc29bac401085b0167a3cad1bd905809a45060822f39f66d2874b1aab8093766ba16ad6b36b5ba67d00584bf4bb41021895a75457d77e3fdba7e7e489ebadf98ba54473409f64bccdd7cfd71471e7e27fed5fe57b30dce07377d1141c8d04b25d4e69269d7e2db6344531a517b4754b922b774ed5650751f872ce7c189071c27ad4843a6130e9a153f75a215fd500468313395da1abd893d5711aa029bdb763262edac6e6ea3bca2524fadd2d41be349bec93b83946e9f047edf790a031b7b7e1389d35aaa73647d8a2030a4ce20bad38e571e493de96a5614ee3f61f08e67759cc5b4b55a8e50670516b5f3ffbd28e219674325681e95ef22c6675a8079cfffea33a502674467c7b0b2aa2de267cc244dc0fc450e610a67924ad2ea62a48c6667ac89df6ff5f2097b05736a1c6bcf3dbc5d3a2f9879b99b7dff1d816691d2ff789e9483f6b7365bc285804918718d184c770b90e6cf666c0bc87818a57623dce37685c2d09a18046350d4aa9e33a2c67ca2665460c96eb874c8a4a98f64cdb15ae4d11e1fe275813b8419e6a67fefe492edeebdad5c34227b40c708fe91734074cafbb555d8ff9c83933df1ccc03ca932477663fd8483db63c78752d07b0edc67559408ddf3c2bb4235b77be22b814b8690a548b899ec18b3a86e2bbde8982a80b674647ed994aef0656b15a80a8e73a11ab7ecfe5301702228a56e803fbcd3e5d089595abff88168652261a414a2e27e08acc3694b0acc220da66a89493971a2059e8975778fdc5814b9946525027c7dd1b7e0b6918e9959f013e6a35a373f076305054972559236a15ae856ca7f61090599694bc79ac66642842c36136e4ae94c1d84e0871a4aa03f61107a456e93b3cbef4c71a6cfc3fb5b5916820e630a2c983271b81c36363637651482166bd95ac4d576f14260a16209e2717968fdc376e56f1f22516d25840dd33b6951f6422ce1140b47dca07253de378d3f4a97a41aaf7a3d7340edd1e7b7db7537c3749eb2537d9fdfeca3981825e941d0f7a87cdc1f645680ed76a864de19b973e963886e254f68c0d0f40d140cfd208f62f3e787769b1ee56d4da7202f0a483ca48e9011057abfb84a4a536465d63ac7edfcff9f7b3e5ff9cc30adf858ffadf9b67528e7d458f93f39cc666b0476fb881567e6fb8f7d22f71e906751e29dabf288918e672d375b1544b46a840861028061034b6102963767dd21676bbe8aea92671e6e5ad3a0ccec620a60ca6103085367e9a35ee44174f7396101ed6102e96726b491bd068b3539f561023661015b6101c373c84d43ca2a71b5acd1570298c8cd98d824d971073c67188a4e60dd55e11767b924c7f7f334da8c1932736ebe4dec4149e7d1647b45b0b11be269bd5decf33f73e2735f5a04aa9eaeb37c2cd27df3c89725c1c5c33f67ae3098d2b28a4762600e1c38414467f7593724ba183737672a62b5e492052f596787cc10d0db58f920086102525467f3e2da3205a9140a15506103b36102d96101daf03473075bde1271873fcf90d48d569e64a87d39645f2e3f73306c685c64dfee8be674ffca192ea8cf5a5a5b293b678ff70741ca00aee060351c596756a5d8d3c911e654678391abe452147dbb0567fa7d4e22d26a459267bbd9f33b7cdd682f0261017e54503d67e2bf44407f039ddf67af2c49cac3cc13f20144676723d38a810bb6a6670c90e1cc13697346046756adddb3437a17bf6727fa9fd11d07e3a11167632aa0a52087ca2d6753293794738244eb076798c3feb1c6e611af679a471bd4dc6b915e02648c9d9aff90366102b05167568ab488b8735df767fd63dcd2feb743160267e7bf2eff80e31526601b5b1b60dc60405373ec64253eb4167d0ce0429b047f114113b5a2b1bb3b678e6fdecf0d8e5d9d6713315b6b0f8dc4f4165b443067a7473b9a72f2549c60111b326738c99042630d9b8767ecccd2ab8a30a679679fdf3e53e193c55c09670a5c6483af6ef3d2675f1894412ab20c1907677b7c41f401620d28602d1c672e19dba98196c817674f75bc85e925c1ce10327373c8c52e68f124897aa3d30dc496c6be165901523b3461019561032461018a7339726f8dc2aa28c102c4696668d3b0757adbdfdd3c61032335413867e62328d141c490956787c398677193b7b210336726e09e4db45df6af67b0609178440b1200016103d55161035e61027e61018039433467fd3c4c1f3814d00667d29806d458e4a887679f6648c8bb33de7a0944436cd3c87ab0786a1bb7ef8a464c1c677525f6343b5626b460291b611e6c566724f1bee73692018f60181b60546103c661029e393d678a646e59a3b4f9cf60181d6101e060776102ca6102c3610316737cc8519a6eb132995bdacee25a9d7c15550121e66103c4f267cd9211718c2aa89a67c9c73483aa20698b0567a288fa48d6c656806722f6fe9eb772b9a7176102d9608a6024f03d67c07f3c069355f93767acbf6f6906afc6a667a3b31b3ee40617680960e2403367cdccec33f5703d5267eef41b1fd8e4aa8b67406e389dace9399a0945446706c4ce6dfa1f859367aa24dee020ac7b06063067876ed165adc4372067933c7a1667e7dc520367f78437b745121b7b60261c675407a1d67bb53a9667554dca3f483cd996197358e72a9c045fb0bae82c491d2e1d84c5cf691a7e3b67491dd20f9c539244675eaf3c84dcfaa16418597ffba55820598810055330f10b5f672b32049ad8e6996cdb0f67f7a10bcfedd39b60101a7318c6fd41b2729c1e14954f24278fa957f155941f3b6102766103ca610133607a73304593190771d419c04fb76ee5abe145e48ff38b610156fa41739cba807568347e5961cb20eb6d5ac5c517d1b1ba3f42678cc5a9a8559d62dd601f1c60946102ab61012e3e70dbe9912934546369d4fe0456b8803cd705657f3106a3296e73a0365bd4c56f602c9dc86e6fb463ea620a2c8d1c66808445edb91b0a7cdc37a19e53f67443b7a1d28bbc667564d7285290bb13386d4b3534fee07b71dbff2e1517a9b683117fa4645ef4a27a34e2ed8185ce0728db1d66613d657964a4387d9055bd70c895a6cdaf54a91945b458484ebe31fe20097ed7b3ef906a9c0587b2d5685068a02eeb5d9dfab58944395740ce9352e0816561ce8a74d246aaa50986a88b1d1815e57de99f561797bcb76162e3f5606c782319a4a4ce987d0473089f3a6cf79cdbf90ca3d2565d6c28abf6682f91b479cf057be413640d040aa68a9e3a60d36103985360bb61037b6103dc39610311609e6101faf061012135434567d29285d598771b7667678095dd15c5b4d40a6706b21551f575a90067e7d5f31066f0e57f19426766051882168d0fda6709c72bb059af11520767a2913d2a3f11d2a267018e38a9fe15777d17604861036061037e6102dd735756dc7853ef4a0bf5d88a584c89d21f8cb7674c610166f4446742d17729f9065c78675ae94f0d406ad0ac675b3643b96d79848308609b40507f7d7137625160f3a8731f403a44de517fc969f5bc85e457eba3a976ec54d16cf461029f556103ca610288604261021d61016673f64c07d6a59b6a4e97b59e8785538b8930ecf3cb610366f1606d5443672b82ebee5ee95b4d67791796333915124b0b67e5662a85c090a55c679b4a669012e1d94a196101286103756103af397fca08f1ec73c60f7e3e40abb074716f2e3d3a3ac58411be8de97c194b50e20fbf61018555
PUSH2 4e7e
PUSH8 4fb87cc2d90eda34
PUSH8 16ddb46d033b432f
AND
PUSH24 e1183a7c67c851296d5e7665ca56e7dd2158341bdb43fac7
PUSH1 af
PUSH2 0348
PUSH2 0154
PUSH2 02dc
PUSH20 f9be0ce6ff661facc3be2288534765a056c1ac81
PUSH2 0169
DELEGATECALL
PUSH15 8d4b95ce3bd940e60687688ec7d9b6
PUSH24 1bb0d8b79e269479c5828966eb6449d66f267a8524933020
PUSH3 d35abc
PUSH29 9b12b8365060660f8462edfefc847086df38ccd44a9d262a1dd50555b8
PUSH10 2e2eddd62e1cbb07c9a6
PUSH12 9a237026291f95884b8fe266
PUSH20 544d46c8936bea177da53e3c1312bda38f4f3ba0
PUSH9 f5e8a91c3bc73e6709
PUSH27 f9f36c4e149ef38103c0552d7e092461a137d5c499717f923f5f2f
PUSH6 b6f992507ee1
PUSH29 0b6c470b9a437ad922daacd9285ef18b6edd4eab3613ab326052e3c802
PUSH9 e0b0d6226bb814137a
PUSH11 c1987fc7638244c9442b47
PUSH7 d5a92878349dd8
DUP14
PUSH8 b6eef9a072a2abcd
PUSH8 a13f347c0bb49209
EXP
PUSH23 7b52cecf065119c1819a817d07ee8cc663a26ec09c089b
PUSH9 2696cf5a850c1df195
PUSH16 e90bff18d0ff36bfa6f2cc25b1b60849
PUSH20 dacbe5081a45f170b8743ed31da4d868e7932dd6
PUSH19 c767f9ac5e9d68488912397af74cf68c291efe
PUSH14 95e3d53d0037474e40edd89d6800
PUSH22 6622c06f5860c016f8a9bbddb445a54a6ea769cc97d7
PUSH20 82e2f2409561485dbfc9d3932cdd0fb9eac8151d
PUSH8 05bb89ddcd62ce98
PUSH19 95c6dd56a8576d09e0cf2c6f3cc6fdf304d8f4
PUSH15 402e6f145a4c4a18e3cbeb7d6e687c
SWAP10
PUSH32 c1efa359cdbae6d6e94c6744813fce07d2a7f3383cddb72a4c2023a8f9b13f21
PUSH1 11
BYTE
PUSH8 2eff1825f5f63a70
PUSH1 38
SHL
PUSH31 c873b9effc596d42b79b14c4cef32881f60d56d1b91327bd9f6a028fb7f368
PUSH8 7d1cfb92b27e2c45
PUSH8 cddfd280cc1ddbe0
SDIV
...
STATICCALL
COINBASE
PUSH20 9cba807568347e5961cb20eb6d5ac5c517d1b1ba
EXTCODEHASH
TIMESTAMP
PUSH8 8cc5a9a8559d62dd
PUSH1 1f
SHR
PUSH1 94
PUSH2 02ab
PUSH2 012e
RETURNDATACOPY
PUSH17 dbe9912934546369d4fe0456b8803cd705
PUSH6 7f3106a3296e
PUSH20 a0365bd4c56f602c9dc86e6fb463ea620a2c8d1c
PUSH7 808445edb91b0a
PUSH29 dc37a19e53f67443b7a1d28bbc667564d7285290bb13386d4b3534fee0
PUSH28 71dbff2e1517a9b683117fa4645ef4a27a34e2ed8185ce0728db1d66
PUSH2 3d65
PUSH26 64a4387d9055bd70c895a6cdaf54a91945b458484ebe31fe2009
PUSH31 d7b3ef906a9c0587b2d5685068a02eeb5d9dfab58944395740ce9352e08165
PUSH2 ce8a
PUSH21 d246aaa50986a88b1d1815e57de99f561797bcb761
PUSH3 e3f560
PUSH13 782319a4a4ce987d0473089f3a
PUSH13 f79cdbf90ca3d2565d6c28abf6
PUSH9 2f91b479cf057be413
PUSH5 0d040aa68a
SWAP15
GASPRICE
PUSH1 d3
PUSH2 0398
MSTORE8
PUSH1 bb
PUSH2 037b
PUSH2 03dc
CODECOPY
PUSH2 0311
PUSH1 9e
PUSH2 01fa
CREATE
PUSH2 0121
CALLDATALOAD
NUMBER
GASLIMIT
PUSH8 d29285d598771b76
PUSH8 678095dd15c5b4d4
EXP
PUSH8 06b21551f575a900
PUSH8 e7d5f31066f0e57f
NOT
TIMESTAMP
PUSH8 66051882168d0fda
PUSH8 09c72bb059af1152
SMOD
PUSH8 a2913d2a3f11d2a2
PUSH8 018e38a9fe15777d
OR
PUSH1 48
PUSH2 0360
PUSH2 037e
PUSH2 02dd
PUSH20 5756dc7853ef4a0bf5d88a584c89d21f8cb7674c
PUSH2 0166
DELEGATECALL
DIFFICULTY
PUSH8 42d17729f9065c78
PUSH8 5ae94f0d406ad0ac
PUSH8 5b3643b96d798483
ADDMOD
PUSH1 9b
BLOCKHASH
POP
PUSH32 7d7137625160f3a8731f403a44de517fc969f5bc85e457eba3a976ec54d16cf4
PUSH2 029f
SSTORE
PUSH2 03ca
PUSH2 0288
PUSH1 42
PUSH2 021d
PUSH2 0166
PUSH20 f64c07d6a59b6a4e97b59e8785538b8930ecf3cb
PUSH2 0366
CALL
PUSH1 6d
SLOAD
NUMBER
PUSH8 2b82ebee5ee95b4d
PUSH8 791796333915124b
SIGNEXTEND
PUSH8 e5662a85c090a55c
PUSH8 9b4a669012e1d94a
NOT
PUSH2 0128
PUSH2 0375
PUSH2 03af
CODECOPY
PUSH32 ca08f1ec73c60f7e3e40abb074716f2e3d3a3ac58411be8de97c194b50e20fbf
PUSH2 0185
SSTORE
========stats==========
instructions: 2566
gas (all instructions: 496028
PUSH8 | 16.250974%
PUSH2 | 12.081060%
PUSH1 | 6.157443%
PUSH20 | 3.078722%
PUSH4 | 1.831645%
PUSH5 | 1.831645%
PUSH15 | 1.831645%
PUSH16 | 1.792673%
PUSH19 | 1.753702%
PUSH29 | 1.753702%
PUSH22 | 1.675760%
PUSH7 | 1.597818%
PUSH27 | 1.597818%
PUSH30 | 1.597818%
PUSH25 | 1.558846%
PUSH31 | 1.519875%
PUSH3 | 1.480904%
PUSH6 | 1.480904%
PUSH28 | 1.363991%
PUSH10 | 1.286048%
PUSH14 | 1.286048%
PUSH11 | 1.247077%
PUSH12 | 1.247077%
PUSH24 | 1.247077%
PUSH26 | 1.247077%
PUSH9 | 1.208106%
PUSH13 | 1.169135%
PUSH17 | 1.169135%
PUSH18 | 1.130164%
PUSH21 | 1.091193%
PUSH23 | 1.091193%
PUSH32 | 1.052221%
EXP | 0.740452%
MULMOD | 0.623539%
SHL | 0.623539%
JUMPDEST | 0.623539%
BYTE | 0.506625%
OR | 0.467654%
SHR | 0.467654%
DIV | 0.428683%
ADD | 0.389712%
NOT | 0.389712%
CREATE | 0.389712%
MUL | 0.350740%
SUB | 0.350740%
SDIV | 0.350740%
SMOD | 0.350740%
ADDMOD | 0.350740%
SAR | 0.350740%
NUMBER | 0.350740%
SIGNEXTEND | 0.311769%
XOR | 0.311769%
GASPRICE | 0.311769%
DIFFICULTY | 0.311769%
SLOAD | 0.311769%
SSTORE | 0.311769%
CALL | 0.311769%
MOD | 0.272798%
AND | 0.272798%
CODECOPY | 0.272798%
EXTCODESIZE | 0.272798%
EXTCODECOPY | 0.272798%
RETURNDATASIZE | 0.272798%
GASLIMIT | 0.272798%
DUP7 | 0.272798%
SWAP13 | 0.272798%
CODESIZE | 0.233827%
EXTCODEHASH | 0.233827%
BLOCKHASH | 0.233827%
COINBASE | 0.233827%
MLOAD | 0.233827%
DUP10 | 0.233827%
SWAP16 | 0.233827%
CALLCODE | 0.233827%
STATICCALL | 0.233827%
ADDRESS | 0.194856%
ORIGIN | 0.194856%
CALLDATASIZE | 0.194856%
TIMESTAMP | 0.194856%
POP | 0.194856%
MSTORE8 | 0.194856%
SWAP10 | 0.194856%
SWAP11 | 0.194856%
SWAP12 | 0.194856%
CREATE2 | 0.194856%
REVERT | 0.194856%
CALLER | 0.155885%
CALLVALUE | 0.155885%
JUMP | 0.155885%
JUMPI | 0.155885%
PC | 0.155885%
GAS | 0.155885%
DUP11 | 0.155885%
DUP13 | 0.155885%
DUP14 | 0.155885%
DUP16 | 0.155885%
SWAP1 | 0.155885%
SWAP6 | 0.155885%
SWAP7 | 0.155885%
SWAP8 | 0.155885%
DELEGATECALL | 0.155885%
STOP | 0.116913%
CALLDATALOAD | 0.116913%
RETURNDATACOPY | 0.116913%
MSTORE | 0.116913%
MSIZE | 0.116913%
DUP2 | 0.116913%
DUP4 | 0.116913%
DUP5 | 0.116913%
DUP8 | 0.116913%
DUP15 | 0.116913%
SWAP2 | 0.116913%
SWAP4 | 0.116913%
SWAP5 | 0.116913%
SWAP9 | 0.116913%
SELFDESTRUCT | 0.116913%
LT | 0.077942%
SHA3 | 0.077942%
CALLDATACOPY | 0.077942%
DUP1 | 0.077942%
DUP6 | 0.077942%
DUP9 | 0.077942%
SWAP3 | 0.077942%
SWAP14 | 0.077942%
UNOFFICIAL_DUP | 0.077942%
UNOFFICIAL_SWAP | 0.077942%
RETURN | 0.077942%
GT | 0.038971%
ISZERO | 0.038971%
BALANCE | 0.038971%
DUP3 | 0.038971%
SWAP15 | 0.038971%
LOG1 | 0.038971%
LOG3 | 0.038971%
LOG4 | 0.038971%
UNOFFICIAL_PUSH | 0.038971%

```


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

evmcodegen-0.1.3.tar.gz (6.6 MB view details)

Uploaded Source

Built Distributions

evmcodegen-0.1.3-py3.5.egg (6.5 MB view details)

Uploaded Source

evmcodegen-0.1.3-py3-none-any.whl (6.5 MB view details)

Uploaded Python 3

File details

Details for the file evmcodegen-0.1.3.tar.gz.

File metadata

  • Download URL: evmcodegen-0.1.3.tar.gz
  • Upload date:
  • Size: 6.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.19.1 setuptools/2.2 requests-toolbelt/0.8.0 tqdm/4.26.0 CPython/3.4.3

File hashes

Hashes for evmcodegen-0.1.3.tar.gz
Algorithm Hash digest
SHA256 52959eae98d8d77c97b85a2f9382ce42599091111aaeca546dd2fde30bb1420e
MD5 13352a9b6590d5b7730716e91aa1bd17
BLAKE2b-256 fc19cfbd8b89108fec331625bdb64bc8f75abaaf327a5df1a2a5b5678ab83450

See more details on using hashes here.

File details

Details for the file evmcodegen-0.1.3-py3.5.egg.

File metadata

  • Download URL: evmcodegen-0.1.3-py3.5.egg
  • Upload date:
  • Size: 6.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.19.1 setuptools/2.2 requests-toolbelt/0.8.0 tqdm/4.26.0 CPython/3.4.3

File hashes

Hashes for evmcodegen-0.1.3-py3.5.egg
Algorithm Hash digest
SHA256 5c2714f28eb4ebe0b80be21385fa51ae534fdc4c33a036c3af394eef67482a32
MD5 40e94e39a214c5d1b601c57a857d25b6
BLAKE2b-256 fdefd3031db0b5e006e2d10ae91f96078f5a3aeda91255891946c71a3aac29ac

See more details on using hashes here.

File details

Details for the file evmcodegen-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: evmcodegen-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 6.5 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.19.1 setuptools/2.2 requests-toolbelt/0.8.0 tqdm/4.26.0 CPython/3.4.3

File hashes

Hashes for evmcodegen-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 2b74de54b2ff2a8afd60d2f37c734b2956bbb58b8ca8e1e74ba82d0042c734d3
MD5 445fa25c1bf1466e8e499215d8978180
BLAKE2b-256 c86823134e56d138cf4e4c9a1a79b0546837cfb55795e5eb756408e2e33dad20

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page