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 hashes)

Uploaded Source

Built Distributions

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

Uploaded Source

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

Uploaded Python 3

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