diff --git a/Cargo.toml b/Cargo.toml index dac7f3d..3e57c9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ wasm-bindgen = { version = "0.2", optional = true } [features] python = ["dep:pyo3"] javascript = ["dep:wasm-bindgen"] +wasm = [] # for dev trace = [] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..76b26e3 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +.PHONY: wasm +wasm: + cargo build --target wasm32-unknown-unknown --features wasm --release + cp target/wasm32-unknown-unknown/release/evmole.wasm go/evmole.wasm diff --git a/evmole.wasm b/evmole.wasm new file mode 100755 index 0000000..fd4d31c Binary files /dev/null and b/evmole.wasm differ diff --git a/go/evmole.go b/go/evmole.go new file mode 100644 index 0000000..13d9b94 --- /dev/null +++ b/go/evmole.go @@ -0,0 +1,78 @@ +package evmole + +import ( + "context" + _ "embed" + "encoding/binary" + "fmt" + + "github.com/tetratelabs/wazero" +) + +//go:embed evmole.wasm +var evmoleWASM []byte + +// FunctionSelectors tries to extract from the given bytecode the function selectors. +func FunctionSelectors(ctx context.Context, code []byte) ([][4]byte, error) { + // Create a new WebAssembly runtime + runtime := wazero.NewRuntime(ctx) + defer func() { _ = runtime.Close(ctx) }() + + instance, err := runtime.Instantiate(ctx, evmoleWASM) + if err != nil { + panic(fmt.Errorf("failed to instantiate WASM module: %w", err)) + } + defer func() { _ = instance.Close(ctx) }() + + gasLimit := 0 + + memory := instance.Memory() + functionSelectorsFunc := instance.ExportedFunction("function_selectors") + if functionSelectorsFunc == nil { + panic("could not find exported function: function_selectors") + } + + codeOffset := uint32(0) + resultLenOffset := uint32(len(code)) + resultOffset := resultLenOffset + 4 + resultCapacity := uint32(512 * 4) + + // Write input to memory + ok := memory.Write(codeOffset, code) + if !ok { + return nil, fmt.Errorf("failed to write input to memory") + } + + // Call the WASM function + results, err := functionSelectorsFunc.Call(ctx, + uint64(codeOffset), uint64(len(code)), uint64(gasLimit), + uint64(resultLenOffset), uint64(resultOffset), uint64(resultCapacity)) + if err != nil { + return nil, fmt.Errorf("failed to call function_selectors: %w", err) + } + + if status := uint32(results[0]); status != 0 { + return nil, fmt.Errorf("error: status=%d", status) + } + + // Read the actual result length + rawResultLen, ok := memory.Read(resultLenOffset, 4) + if !ok { + return nil, fmt.Errorf("failed to read result length") + } + resultLen := binary.LittleEndian.Uint32(rawResultLen) + + // Success, read the result + result, ok := memory.Read(resultOffset, resultLen) + if !ok { + return nil, fmt.Errorf("failed to read result from memory") + } + + // Convert to [][4]byte + selectors := make([][4]byte, len(result)/4) + for i := 0; i < len(result); i += 4 { + copy(selectors[i/4][:], result[i:i+4]) + } + + return selectors, nil +} diff --git a/go/evmole.wasm b/go/evmole.wasm new file mode 100755 index 0000000..e586bd6 Binary files /dev/null and b/go/evmole.wasm differ diff --git a/go/evmole_test.go b/go/evmole_test.go new file mode 100644 index 0000000..0f790a7 --- /dev/null +++ b/go/evmole_test.go @@ -0,0 +1,98 @@ +package evmole_test + +import ( + "bytes" + "context" + "encoding/hex" + "testing" + + evmole "github.com/cdump/evmole/go" +) + +func TestFunctionSelectors(t *testing.T) { + // Code for 0xef484de8C07B6e2d732A92B5F78e81B38f99f95E + bytecodeStr := `5f3560e01c600560056007831602614f3a01601b395f51600760078260ff16848460181c0260181c06028260081c61ffff1601601939505f51818160181c14600336111661004c57612ef8565b8060fe16361034826001160217614f36578060081c61ffff16565b600260405260206040f35b602061513e60403960206040f35b602061517e60403960206040f35b6020600435602061519e5f395f51811015614f365760051b60800161513e0160403960206040f35b602060043560206152fe5f395f51811015614f365760051b6101e00161513e0160403960206040f35b60035460405260206040f35b60045460405260206040f35b64012a05f20060405260206040f35b60055460405260206040f35b60065460405260206040f35b60075460405260206040f35b60085460405260206040f35b600435600954811015614f3657600a015460405260206040f35b60145460405260206040f35b60155460405260206040f35b60165460405260206040f35b60208060405280604001602060206154de5f395f5101806154de8339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b602080604052806040016020602061553e5f395f51018061553e8339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b601260405260206040f35b60208060805260066040527f76372e302e30000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506080f35b6004358060a01c614f365760405260176040516020525f5260405f205460605260206060f35b6004358060a01c614f36576040526024358060a01c614f365760605260186040516020525f5260405f20806060516020525f5260405f2090505460805260206080f35b6004358060a01c614f3657604052601a6040516020525f5260405f205460605260206060f35b60206155be60403960206040f35b33610a2052610330565b6084358060a01c614f3657610a20525b60043580600f0b8118614f36576109e05260243580600f0b8118614f3657610a00525f54600214614f365760025f55602033610760526109e05161078052610a00516107a052604060446107c037610a2051610800525f61082052610396610a4061432d565b610a4060035f55f35b33610a20526103b9565b6084358060a01c614f3657610a20525b60043580600f0b8118614f36576109e05260243580600f0b8118614f3657610a00525f54600214614f365760025f55602061543e5f395f51614f3657602033610760526109e05161078052610a00516107a052604060446107c037610a20516108005260016108205261042d610a4061432d565b610a4060035f55f35b336107a052610450565b6084358060a01c614f36576107a0525b60043580600f0b8118614f36576107605260243580600f0b8118614f3657610780525f54600214614f365760025f556107a05115614f36576104936108006135fc565b61080060406107c060408360045afa50506104af6108406137fb565b610840604061080060408360045afa50506040604060406107c060045afa5060406080604061080060045afa506104e761088061394d565b610880604061084060408360045afa505060e036610880376001610760511261052957610760516001810380600f0b8118614f365790506108a05260016108e0525b6107805161055657602060206152fe5f395f5115614f36575f60051b6101e00161513e0161094039610599565b610780516001810380600f0b8118614f365790506108c05260016109005260206108c051602061519e5f395f51811015614f365760051b60800161513e01610940395b6108e051610320526108a051610340526044356103605233610380525f6103a05260016107605112156105cc575f6105d5565b60016107805112155b6103c0526105e46109806131f3565b6109805161096052610760516105fb576001610601565b61078051155b6106e857610940516370a0823161098052306109a0526020610980602461099c845afa610630573d5f5f3e3d5ffd5b60203d10614f365761098090505161088052602061513e5f395f51633df02124610980526108a0516109a0526108c0516109c052610960516109e052606435610a0052803b15614f36575f610980608461099c5f855af1610693573d5f5f3e3d5ffd5b50610940516370a0823161098052306109a0526020610980602461099c845afa6106bf573d5f5f3e3d5ffd5b60203d10614f365761098090505161088051808203828111614f365790509050610880526108a0565b6108e05160018111614f365760051b6108400151670de0b6b3a7640000610960516108e05160018111614f365760051b6107c00151808202811583838304141715614f36579050905004808201828110614f36579050905061092052610920516102e0526040610300604061084060045afa50604061034060406107c060045afa506108e05161038052610900516103a052610785610980613f75565b61098051610880526109005160018111614f3657600101805461088051808203828111614f3657905090508155506001610780511261089357610940516370a082316109a052306109c05260206109a060246109bc845afa6107e9573d5f5f3e3d5ffd5b60203d10614f36576109a090505161098052602061513e5f395f51631a4d01d26109a052610880516109c0526108c0516109e0525f610a0052803b15614f36575f6109a060646109bc5f855af1610842573d5f5f3e3d5ffd5b50610940516370a082316109a052306109c05260206109a060246109bc845afa61086e573d5f5f3e3d5ffd5b60203d10614f36576109a090505161098051808203828111614f365790509050610880525b6064356108805110614f36575b6109405163a9059cbb610980526107a0516109a052610880516109c0526020610980604461099c5f855af16108d7573d5f5f3e3d5ffd5b3d6108ee57803b15614f365760016109e052610907565b60203d10614f3657610980518060011c614f36576109e0525b6109e090505115614f3657337fd013ca23e77a65003c2c659c5442c00c805371b7fc1ebd4c206c41d1536bd90b61076051610980526044356109a052610780516109c052610880516109e0526080610980a2602061088060035f55f35b336104e05261097e565b6064358060a01c614f36576104e0525b5f54600214614f365760025f556104e05115614f365761099f6105206139cf565b61052051610500526109b26105606137fb565b610560604061052060408360045afa50506109ce6105a06135fc565b6105a0604061056060408360045afa50506040610120604061056060045afa506040610160604061052060045afa50610500516101a052610a106105c06145bb565b6105c0516105a0526019546105c05260406105e0604061052060045afa505f6002905b80610620526106205160018111614f365760051b6004013515610ada576106205160018111614f365760051b6105e001805161062051610320527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610340526106205160018111614f365760051b600401356103605233610380526040366103a037610ac06106406131f3565b61064051808201828110614f365790509050815250610ae4565b6105c05115614f36575b600101818118610a335750506040610120604061056060045afa50604061016060406105e060045afa50610500516101a052610b216106406145bb565b61064051610620526105a051610620511115614f3657606036610640376105c05115610ebf576060366106a0376105a05161062051808201828110614f36579050905060011c610700526040366107203760035460011b60021c610760525f6002905b8061078052610620516107805160018111614f365760051b6105200151808202811583838304141715614f3657905090506105a0518015614f3657808204905090506106a0526107805160018111614f365760051b6105e001516106e0526106e0516106a05111610c01576106a0516106e051036106c052610c0f565b6106e0516106a051036106c0525b670de0b6b3a76400006107805160018111614f365760051b61056001516107805160018111614f365760051b61052001516106e051808201828110614f365790509050808202811583838304141715614f3657905090500461072052610720516040526107005160605261076051608052610c8b6107a0613ada565b6107a051610740526402540be400610740516106c051808202811583838304141715614f365790509050046107805160018111614f365760051b610640015261078051600954811015614f3657600a0180546402540be4006107805160018111614f365760051b610640015164012a05f20081028164012a05f200820418614f3657905004808201828110614f3657905090508155506107805160018111614f365760051b6105e00180516107805160018111614f365760051b6106400151808203828111614f365790509050815250600101818118610b8457505060406040604061056060045afa506040608060406105e060045afa50610d8e6107c061394d565b6107c0604061078060408360045afa505060206152be5f395f516350e7277d6107c0526060806107e052806107e0015f61078051610980526107a0516109a0526002610960525f610960518084528060051b5f8260088111614f36578015610e1057905b8060051b61098001518160051b602089010152600101818118610df2575b50508201602001915050905090508101905061050051610800526002610820525060206107c06101846107dc845afa610e4b573d5f5f3e3d5ffd5b60203d10614f36576107c0905051610620526105a0516105c051610620516105a051808203828111614f365790509050808202811583838304141715614f36579050905004610680526040610140604061078060045afa506105005161018052610620516101a052610f3a613de256610f3a565b61062051610680526106205160405261062051606052610ee06106a0612efc565b6106a051601355601654604052610ef86106e0613b9a565b6106e060406106a060408360045afa5050426106c0511015610f3a57426106c0526106a0516040526106c051606052610f326106e0612efc565b6106e0516016555b604435610680511015610fac5760146106a0527f536c697070616765207363726577656420796f750000000000000000000000006106c0526106a0506106a051806106c001601f825f031636823750506308c379a061066052602061068052601f19601f6106a051011660440161067cfd5b6105c05161068051808201828110614f3657905090506105c05260176104e0516020525f5260405f20546106a052610680516106a0510160176104e0516020525f5260405f20556105c0516019556104e0515f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610680516106c05260206106c0a3337f189c623b666b1b45b83d7178f39b8c087cb09774317ca2f53c2d3c3726f222a26080806106c052806106c0015f604060046109a0376002610980525f610980518084528060051b5f8260088111614f365780156110a757905b8060051b6109a001518160051b602089010152600101818118611089575b505082016020019150509050905081019050806106e052806106c0015f61064051610ac05261066051610ae0526002610aa0525f610aa0518084528060051b5f8260088111614f3657801561111657905b8060051b610ac001518160051b6020890101526001018181186110f8575b50508201602001915050905090508101905061062051610700526105c051610720526106c0a2602061068060035f55f35b336107a052611161565b6064358060a01c614f36576107a0525b60243580600f0b8118614f3657610780525f54600214614f365760025f5560043515614f365760c0366107c0376004356102005261078051610220526111a86108806146b2565b61088080516107c05260208101516107e05260408101604061080060408360045afa505060808101516108405260a081015161086052506044356107c0511015611251576018610880527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006108a0526108805061088051806108a001601f825f031636823750506308c379a061084052602061086052601f19601f61088051011660440161085cfd5b61078051600954811015614f3657600a0180546402540be4006107e05164012a05f20081028164012a05f200820418614f3657905004808201828110614f365790509050815550336040526004356060526112aa614caf565b610780516040526107c0516060526107a0516080526112c761342c565b337f6f48129db1f37ccb9cc5dd7e119cb32750cabdf75b48375d730d26ce3659bbe161078051610880526004356108a0526107c0516108c0526019546108e0526080610880a26040610140604061080060045afa506108405161018052610860516101a052611334613de2565b60206107c060035f55f35b336104c052611359565b6064358060a01c614f36576104c0525b5f54600214614f365760025f556113716105006139cf565b610500516104e0526113846105406135fc565b610540604061050060408360045afa50506113a06105806137fb565b610580604061054060408360045afa50506040610120604061050060045afa506040610160604061054060045afa506104e0516101a0526113e26105a06145bb565b6105a0516105805260406105a0604061054060045afa505f6002905b806105e0526105e05160018111614f365760051b6004013515611480576105e05160018111614f365760051b6105a00180516105e05160018111614f365760051b60040135808203828111614f3657905090508152506105e0516040526105e05160018111614f365760051b600401356060526104c05160805261148061342c565b6001018181186113fe5750506040610120604061050060045afa50604061016060406105a060045afa506104e0516101a0526114bd6106006145bb565b610600516105e05260035460011b60021c61060052610580516105e051808201828110614f36579050905060011c6106205260e036610640375f6002905b80610720526105e0516107205160018111614f365760051b6105400151808202811583838304141715614f365790509050610580518015614f3657808204905090506106c0526107205160018111614f365760051b6105a0015161070052610700516106c05111611578576106c05161070051036106e052611586565b610700516106c051036106e0525b670de0b6b3a76400006107205160018111614f365760051b61050001516107205160018111614f365760051b610540015161070051808201828110614f365790509050808202811583838304141715614f365790509050046106a0526106a0516040526106205160605261060051608052611602610740613ada565b61074051610680526402540be400610680516106e051808202811583838304141715614f365790509050046107205160018111614f365760051b610640015261072051600954811015614f3657600a0180546402540be4006107205160018111614f365760051b610640015164012a05f20081028164012a05f200820418614f3657905004808201828110614f3657905090508155506107205160018111614f365760051b6105a00180516107205160018111614f365760051b6106400151808203828111614f3657905090508152506001018181186114fb5750506040610120604061050060045afa50604061016060406105a060045afa506104e0516101a05261170f6107206145bb565b610720516105e05260406040604061050060045afa506040608060406105a060045afa5061173e61072061394d565b610720604061076060408360045afa50506104e0516107a0526105e0516107c0526080610140608061076060045afa50611776613de2565b6019546107205261058051610580516105e051808203828111614f36579050905061072051808202811583838304141715614f3657905090500460018101818110614f365790506107405260026107405110614f365760443561074051111561183e576014610760527f536c697070616765207363726577656420796f750000000000000000000000006107805261076050610760518061078001601f825f031636823750506308c379a061072052602061074052601f19601f61076051011660440161073cfd5b3360405261074051606052611851614caf565b337f3631c28b1f9dd213e0319fb167b554d76b6c283a41143eb400a0d1adb1af17556080806107605280610760015f60406004610a40376002610a20525f610a20518084528060051b5f8260088111614f365780156118ca57905b8060051b610a4001518160051b6020890101526001018181186118ac575b505082016020019150509050905081019050806107805280610760015f61064051610b605261066051610b80526002610b40525f610b40518084528060051b5f8260088111614f3657801561193957905b8060051b610b6001518160051b60208901015260010181811861191b575b5050820160200191505090509050810190506105e0516107a0526107205161074051808203828111614f3657905090506107c052610760a2602061074060035f55f35b336102a05260016102c0526119c5565b6064358060a01c614f36576102a05260016102c0526119c5565b6064358060a01c614f36576102a0526084358060011c614f36576102c0525b5f54600214614f365760025f556019546102e05260043515614f3657604036610300376119f36103806137fb565b610380604061034060408360045afa50505f610380525f6002905b806103a0526102e0516103a05160018111614f365760051b6103400151600435808202811583838304141715614f36579050905004610380526103a05160018111614f365760051b60240135610380511015611aee5760306103c0527f5769746864726177616c20726573756c74656420696e20666577657220636f696103e0527f6e73207468616e20657870656374656400000000000000000000000000000000610400526103c0506103c051806103e001601f825f031636823750506308c379a06103805260206103a052601f19601f6103c051011660440161039cfd5b610380516103a05160018111614f365760051b61030001526103a051604052610380516060526102a051608052611b2361342c565b600101818118611a0e57505033604052600435606052611b41614caf565b601654604052611b526103e0613b9a565b6103e060406103a060408360045afa50506013546103e0526fffffffffffffffffffffffffffffffff6103e0511661040052610400516102e05161040051600435808202811583838304141715614f36579050905004808203828111614f365790509050610460526103e0516040526015546060526103c051608052611bd9610420613cba565b610420516104805260406040604061046060045afa50611bfa610440612efc565b61044051601355426103c0511015611c3257426103c0526103a0516040526103c051606052611c2a610420612efc565b610420516016555b337f347ad828e58cbe534d8f6b67985d791360756b18f0d95fd9f197a66cc46480ea6060806104205280610420015f610300516106e052610320516107005260026106c0525f6106c0518084528060051b5f8260088111614f36578015611cb357905b8060051b6106e001518160051b602089010152600101818118611c95575b505082016020019150509050905081019050806104405280610420015f5f82525f5f5f60088111614f36578015611cfc57905b5f8160051b602087010152600101818118611ce6575b5050810160200190509050810190506004356102e0510361046052610420a26102c05115611d2c57611d2c614d1c565b61030051610420526103205161044052604061042060035f55f35b611d4f614d1c565b005b600435614f36576fffffffffffffffffffffffffffffffff6012541660405260206040f35b600435614f365760125460801c60405260206040f35b600435614f3657611d9e6102206139cf565b6102205161020052611db16102606135fc565b610260604061032060408360045afa5050611dcd6102a06137fb565b6102a0604061036060408360045afa505060806040608061032060045afa50611df76102e061394d565b6102e0604061022060408360045afa505060206152be5f395f516350e7277d610280526060806102a052806102a0015f610220516104405261024051610460526002610420525f610420518084528060051b5f8260088111614f36578015611e7957905b8060051b61044001518160051b602089010152600101818118611e5b575b505082016020019150509050905081019050610200516102c05260026102e05250602061028061018461029c845afa611eb4573d5f5f3e3d5ffd5b60203d10614f365761028090505161026052602060406040604061022060045afa50610200516080526102605160a052611eef610280613bbf565b610280f35b5f54600214614f3657600435614f365760206012546040526014546060526fffffffffffffffffffffffffffffffff60165416608052611f35610140613cba565b610140f35b5f54600214614f3657602060135460405260155460605260165460801c608052611f65610140613cba565b610140f35b6004358060a01c614f365760c0523360405260c051606052602435608052611f90614eba565b600160e052602060e0f35b6004358060a01c614f365760c0526024358060a01c614f365760e05260c05160405260e051606052604435608052611fd1614eba565b601860c0516020525f5260405f2080336020525f5260405f20905054610100527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010051146120885761010051604435808203828111614f3657905090506101205261012051601860c0516020525f5260405f2080336020525f5260405f209050553360c0517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92561012051610140526020610140a35b6001610120526020610120f35b6004358060a01c614f36576040526024356018336020525f5260405f20806040516020525f5260405f20905055604051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560243560605260206060a3600160605260206060f35b6004358060a01c614f3657610120526024358060a01c614f3657610140526084358060081c614f3657610160526101205115614f36576064354211614f3657601a610120516020525f5260405f2054610180525f60026101c0527f19010000000000000000000000000000000000000000000000000000000000006101e0526101c08051602082018361032001815181525050808301925050506121a2610200614e27565b610200518161032001526020810190507f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c961024052610120516102605261014051610280526044356102a052610180516102c0526064356102e05260c061022052610220805160208201209050816103200152602081019050806103005261030090508051602082012090506101a052610120513b1561236b575f604060a46102603760406102405261024080516020820183610320018281848460045afa50505080830192505050610160516102a0526102a0601f810180516102e0525060016102c0526102c09050805160208201836103200181518152505080830192505050806103005261030090506020815101806101c0828460045afa5050507f1626ba7e0000000000000000000000000000000000000000000000000000000061012051631626ba7e6102405260406101a051610260528061028052806102600160206101c051018082826101c060045afa50508051806020830101601f825f03163682375050601f19601f82516020010116905081015050602061024060c461025c845afa612353573d5f5f3e3d5ffd5b60203d10614f365761024090505118614f36576123ab565b610120515f610240526101a0516101c052610160516101e05260a4356102005260c43561022052602061024060806101c060015afa506102405118614f36575b6044356018610120516020525f5260405f2080610140516020525f5260405f2090505560016101805101601a610120516020525f5260405f205561014051610120517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9256044356101c05260206101c0a360016101c05260206101c0f35b6020612435610120614e27565b610120f35b60043580600f0b8118614f365760405260243580600f0b8118614f3657606052602060206152de5f395f5163e31593d8608052602060806004609c845afa612484573d5f5f3e3d5ffd5b60203d10614f36576080518060a01c614f365760c05260c09050516383aa796a60e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa6124d8573d5f5f3e3d5ffd5b60203d10614f365760e09050f35b60043580600f0b8118614f365760405260243580600f0b8118614f3657606052602060206152de5f395f5163e31593d8608052602060806004609c845afa612530573d5f5f3e3d5ffd5b60203d10614f36576080518060a01c614f365760c05260c090505163d6fc10ab60e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa612584573d5f5f3e3d5ffd5b60203d10614f365760e09050f35b60043580600f0b8118614f365760405260243580600f0b8118614f3657606052602060206152de5f395f5163e31593d8608052602060806004609c845afa6125dc573d5f5f3e3d5ffd5b60203d10614f36576080518060a01c614f365760c05260c0905051630c601c2c60e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa612630573d5f5f3e3d5ffd5b60203d10614f365760e09050f35b60043580600f0b8118614f365760405260243580600f0b8118614f3657606052602060206152de5f395f5163e31593d8608052602060806004609c845afa612688573d5f5f3e3d5ffd5b60203d10614f36576080518060a01c614f365760c05260c090505163c02c60a660e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa6126dc573d5f5f3e3d5ffd5b60203d10614f365760e09050f35b60243580600f0b8118614f36576107805260206004356102005261078051610220526127176107a06146b2565b6107a0f35b5f54600214614f365760195460405260206040f35b5f54600214614f36576127456102406135fc565b610240604061030060408360045afa50506127616102806137fb565b610280604061034060408360045afa505060806040608061030060045afa5061278b6102c061394d565b6102c0604061020060408360045afa505060206152be5f395f516350e7277d610280526060806102a052806102a0015f610200516104405261022051610460526002610420525f610420518084528060051b5f8260088111614f3657801561280d57905b8060051b61044001518160051b6020890101526001018181186127ef575b50508201602001915050905090508101905061282a6102606139cf565b610260516102c05260026102e05250602061028061018461029c845afa612853573d5f5f3e3d5ffd5b60203d10614f36576102809050516102405261024051670de0b6b3a7640000810281670de0b6b3a7640000820418614f365790506019548015614f365780820490509050610260526020610260f35b6044358060011c614f3657604052602060206152de5f395f5163e31593d8606052602060606004607c845afa6128da573d5f5f3e3d5ffd5b60203d10614f36576060518060a01c614f365760a05260a090505163fb79eb2760c05260608060e0528060e0015f60406004610280376002610260525f610260518084528060051b5f8260088111614f3657801561295257905b8060051b61028001518160051b602089010152600101818118612934575b50508201602001915050905090508101905060405161010052306101205250602060c061018460dc845afa612989573d5f5f3e3d5ffd5b60203d10614f365760c09050f35b60646129a360c06139cf565b60c0510460e052602060e0f35b60206129bc60c06139cf565b60c0f35b60206129cd6102006137fb565b61020060043560018111614f365760051b81019050f35b6129ef6102406137fb565b610240604061020060408360045afa50506020806102405280610240015f610200516103a052610220516103c0526002610380525f610380518084528060051b5f8260088111614f36578015612a5f57905b8060051b6103a001518160051b602089010152600101818118612a41575b505082016020019150509050905081019050610240f35b612a816101806135fc565b610180604061014060408360045afa50506020806101805280610180015f610140516102e052610160516103005260026102c0525f6102c0518084528060051b5f8260088111614f36578015612af157905b8060051b6102e001518160051b602089010152600101818118612ad3575b505082016020019150509050905081019050610180f35b60043580600f0b8118614f365760405260243580600f0b8118614f3657606052602060206152de5f395f5163e31593d8608052602060806004609c845afa612b52573d5f5f3e3d5ffd5b60203d10614f36576080518060a01c614f365760c05260c090505163a63530bd60e05260405161010052606051610120523061014052602060e0606460fc845afa612b9f573d5f5f3e3d5ffd5b60203d10614f365760e09050f35b60206152de5f395f5163f851a44060c052602060c0600460dc845afa612bd5573d5f5f3e3d5ffd5b60203d10614f365760c0518060a01c614f3657610100526101009050513318614f3657600754620151808101818110614f365790504210614f365742620151808101818110614f3657905060243510614f3657612c3260e06139cf565b60e05160c05260043560648102816064820418614f3657905060e05260043515612c6457620f423f6004351115612c66565b5f5b15614f365760c05160e05110612c965760c051600a810281600a820418614f3657905060e05111614f3657612cb2565b60c05160e051600a810281600a820418614f3657905010614f36575b60c05160055560e051600655426007556024356008557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c25460c0516101005260e051610120524261014052602435610160526080610100a1005b60206152de5f395f5163f851a44060c052602060c0600460dc845afa612d33573d5f5f3e3d5ffd5b60203d10614f365760c0518060a01c614f3657610100526101009050513318614f3657612d6060e06139cf565b60e05160c05260c05160055560c05160065542600755426008557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc20193860c05160e0524261010052604060e0a1005b60206152de5f395f5163f851a440604052602060406004605c845afa612dd5573d5f5f3e3d5ffd5b60203d10614f36576040518060a01c614f365760805260809050513318614f365764012a05f20060043511614f36576004356003556802b5e3af16b1880000602435600435808202811583838304141715614f36579050905011614f36576024356004557f750d10a7f37466ce785ee6bcb604aac543358db42afbcc332a3c12a49c80bf6d6040600460403760406040a1005b60206152de5f395f5163f851a440604052602060406004605c845afa612e90573d5f5f3e3d5ffd5b60203d10614f36576040518060a01c614f365760805260809050513318614f36576024356004350215614f36576004356014556024356015557f68dc4e067dff1862b896b7a0faf55f97df1a60d0aaa79481b69d675f2026a28c6040600460403760406040a1005b5f5ffd5b6fffffffffffffffffffffffffffffffff60405111614f36576fffffffffffffffffffffffffffffffff60605111614f365760605160801b60405117815250565b602061515e5f395f511561306d575f6080525f602061517e5f395f5160088111614f36578015612fcc57905b806101a0526060515f8112614f36576101a05118612fa45760805160078111614f36576040518160051b60a001526001810160805250612fc1565b60805160078111614f36575f8160051b60a0015260018101608052505b600101818118612f69575b5050602061513e5f395f5163b72df5de6101a0526040806101c052806101c0015f6080518083528060051b5f8260088111614f3657801561302657905b8060051b60a001518160051b602088010152600101818118613009575b505082016020019150509050810190505f6101e0525060206101a06101646101bc5f855af1613057573d5f5f3e3d5ffd5b60203d10614f36576101a09050518152506131f1565b6020600260206152fe5f395f5110614f3657600160051b6101e00161513e016080396080516370a0823160c0523060e052602060c0602460dc845afa6130b5573d5f5f3e3d5ffd5b60203d10614f365760c090505160a0526002602061517e5f395f51186131375760403660c03760405160605160018111614f365760051b60c00152602061513e5f395f51630b4c7e4d610100526040610120604060c060045afa505f61016052803b15614f36575f610100606461011c5f855af1613135573d5f5f3e3d5ffd5b505b6003602061517e5f395f51186131a95760603660c03760405160605160028111614f365760051b60c00152602061513e5f395f51634515cef3610120526060610140606060c060045afa505f6101a052803b15614f36575f610120608461013c5f855af16131a7573d5f5f3e3d5ffd5b505b6080516370a0823160c0523060e052602060c0602460dc845afa6131cf573d5f5f3e3d5ffd5b60203d10614f365760c090505160a051808203828111614f3657905090508152505b565b60206103205160206152fe5f395f51811015614f365760051b6101e00161513e016103e0395f610400525f61034051121561322e575f613237565b60016103205118155b1561326757602061034051602061519e5f395f51811015614f365760051b60800161513e016103e0396001610400525b6103e0516370a082316104405230610460526020610440602461045c845afa613292573d5f5f3e3d5ffd5b60203d10614f3657610440905051610420526103a051613380576103605115614f36576103e0516323b872dd6104405261038051610460523061048052610360516104a0526020610440606461045c5f855af16132f1573d5f5f3e3d5ffd5b3d61330857803b15614f365760016104c052613321565b60203d10614f3657610440518060011c614f36576104c0525b6104c090505115614f36576103e0516370a082316104405230610460526020610440602461045c845afa613357573d5f5f3e3d5ffd5b60203d10614f365761044090505161042051808203828111614f365790509050610420526133bc565b610400516133bc57610420516103205160018111614f365760010154808203828111614f36579050905061042052610360516104205110614f36575b61040051156133fc576103c051156133da576104205181525061342a565b61042051604052610340516060526133f3610440612f3d565b61044051610420525b6103205160018111614f3657600101805461042051808201828110614f365790509050815550610420518152505b565b60805115614f3657602061543e5f395f516134f45760405160018111614f36576001018054606051808203828111614f365790509050815550602060405160206152fe5f395f51811015614f365760051b6101e00161513e015f395f5163a9059cbb60a05260805160c05260605160e052602060a0604460bc5f855af16134b5573d5f5f3e3d5ffd5b3d6134cc57803b15614f36576001610100526134e4565b60203d10614f365760a0518060011c614f3657610100525b61010090505115614f36576135fa565b602060405160206152fe5f395f51811015614f365760051b6101e00161513e015f395f516370a0823160c0523060e052602060c0602460dc845afa61353b573d5f5f3e3d5ffd5b60203d10614f365760c090505160a052602060405160206152fe5f395f51811015614f365760051b6101e00161513e015f395f5163a9059cbb60c05260805160e05260605161010052602060c0604460dc5f855af161359c573d5f5f3e3d5ffd5b3d6135b357803b15614f36576001610120526135cb565b60203d10614f365760c0518060011c614f3657610120525b61012090505115614f365760a051606051808203828111614f36579050905060405160018111614f3657600101555b565b602061545e604039602061513e5f395f5163bb7b8b80608052602060806004609c845afa61362c573d5f5f3e3d5ffd5b60203d10614f365760809050516060526001602061541e5f395f511861365c57602061547e5f395f51151561365e565b5f5b61370c576003602061541e5f395f51186137ec57670de0b6b3a7640000604051602060206152fe5f395f5115614f36575f60051b6101e00161513e015f395f516307a2d13a608052602061549e60a039602060806024609c845afa6136c5573d5f5f3e3d5ffd5b60203d10614f36576080905051808202811583838304141715614f36579050905060206154be5f395f51808202811583838304141715614f365790509050046040526137ec565b602061547e5f395f5173ffffffffffffffffffffffffffffffffffffffff811690508060a01c614f36575a7fffffffff00000000000000000000000000000000000000000000000000000000602061547e5f395f511660e052602060c05260c050602061012060c05160e08585fa9050905061378a573d5f5f3e3d5ffd5b3d602081183d6020100218610100526101008051608052602081015160a05250602060805118614f365760a05160805160200360031b1c60c052670de0b6b3a764000060405160c051808202811583838304141715614f365790509050046040525b6040816040604060045afa5050565b60403660403760095460208160051b015f81601f0160051c60098111614f3657801561383b57905b80600901548160051b60800152600101818118613823575b505050505f6002905b806101a052602061543e5f395f516138a1576101a05160018111614f3657600101546101a051608051811015614f365760051b60a00151808203828111614f3657905090506101a05160018111614f365760051b60400152613932565b60206101a05160206152fe5f395f51811015614f365760051b6101e00161513e015f395f516370a082316101c052306101e05260206101c060246101dc845afa6138ed573d5f5f3e3d5ffd5b60203d10614f36576101c09050516101a051608051811015614f365760051b60a00151808203828111614f3657905090506101a05160018111614f365760051b604001525b6001018181186138445750506040816040604060045afa5050565b60403660c0375f6002905b8061010052670de0b6b3a76400006101005160018111614f365760051b604001516101005160018111614f365760051b60800151808202811583838304141715614f365790509050046101005160018111614f365760051b60c00152600101818118613958575050604081604060c060045afa5050565b60085460405260065460605260405142106139f357606051815250613ad856613ad8565b60055460805260075460a05260805160605111613a7557608051606051608051034260a051808203828111614f365790509050808202811583838304141715614f36579050905060405160a051808203828111614f3657905090508015614f365780820490509050808203828111614f365790509050815250613ad856613ad8565b608051608051606051034260a051808203828111614f365790509050808202811583838304141715614f36579050905060405160a051808203828111614f3657905090508015614f365780820490509050808201828110614f3657905090508152505b565b60045460a0526402540be40060a05111613af957608051815250613b98565b604051606051808201828110614f3657905090506fffffffffffffffffffffffffffffffff8111614f36576002810a905060c0526402540be4006402540be40060a051038060021b818160021c18614f36579050604051808202811583838304141715614f365790509050606051808202811583838304141715614f36579050905060c0518015614f3657808204905090500160805160a05102048152505b565b6fffffffffffffffffffffffffffffffff60405116815260405160801c602082015250565b60805160011b60c05260a05160021c60e0525f6002905b806101005260e05160a051808202811583838304141715614f3657905090506101005160018111614f365760051b604001518015614f36578082049050905060e052600101818118613bd6575050606460c051604051808202811583838304141715614f36579050905004610100526101005160605160e051604051808202811583838304141715614f36579050905004808201828110614f365790509050670de0b6b3a7640000810281670de0b6b3a7640000820418614f365790506101005160e051808201828110614f3657905090508015614f365780820490509050815250565b6fffffffffffffffffffffffffffffffff6040511660a05260405160801c60c052426080511015613dd95760206152be5f395f5163e46751e361010052606051670de0b6b3a7640000608051420302048060ff1c614f36577f80000000000000000000000000000000000000000000000000000000000000008114614f36575f03610120526020610100602461011c845afa613d58573d5f5f3e3d5ffd5b60203d10614f365761010090505160e052670de0b6b3a764000060a05160e05180670de0b6b3a764000003670de0b6b3a76400008111614f36579050808202811583838304141715614f36579050905060c05160e051808202811583838304141715614f365790509050808201828110614f36579050905004815250613de0565b60c0518152505b565b601654604052613df3610200613b9a565b61020060406101c060408360045afa505060125461020052610200516102205260406040604061014060045afa50610180516080526101a05160a052613e3a610260613bbf565b61026051610240526102405115613eb75761024051671bc16d674ec80000818118671bc16d674ec800008310021890506102a052610200516040526014546060526101c051608052613e8d610260613cba565b610260516102c0526040604060406102a060045afa50613eae610280612efc565b61028051610220525b610220516012556101a0516102a0526013546040526015546060526101e051608052613ee4610260613cba565b610260516102c0526040604060406102a060045afa50613f05610280612efc565b610280516013555f6002905b8061026052426102605160018111614f365760051b6101c001511015613f4757426102605160018111614f365760051b6101c001525b600101818118613f115750506101c0516040526101e051606052613f6c610260612efc565b61026051601655565b613f806103e06139cf565b6103e0516103c05260206152be5f395f516350e7277d610400526060806104205280610420015f610300516105c052610320516105e05260026105a0525f6105a0518084528060051b5f8260088111614f36578015613ff957905b8060051b6105c001518160051b602089010152600101818118613fdb575b5050820160200191505090509050810190506103c0516104405260026104605250602061040061018461041c845afa614034573d5f5f3e3d5ffd5b60203d10614f36576104009050516103e05260206152be5f395f5163aa3ded9b6104205260e061038051610440526103a051610460526102e05161048052806104a05280610440015f610300516106605261032051610680526002610640525f610640518084528060051b5f8260088111614f365780156140cf57905b8060051b61066001518160051b6020890101526001018181186140b1575b5050820160200191505090509050810190506103c0516104c0526103e0516104e05260026105005250602061042061020461043c845afa614112573d5f5f3e3d5ffd5b60203d10614f3657610420905051610400526103a05160018111614f365760051b610300015161040051808203828111614f36579050905060018103818111614f36579050610420526402540be400610420516103805160018111614f365760051b61030001516102e051808201828110614f36579050905060011c6040526103a05160018111614f365760051b610300015161040051808201828110614f36579050905060011c6060526003546080526141ce610460613ada565b61046051808202811583838304141715614f36579050905004610440526104205161044051808203828111614f365790509050670de0b6b3a7640000810281670de0b6b3a7640000820418614f365790506103a05160018111614f365760051b61034001518015614f365780820490509050610420526103a051600954811015614f3657600a0180546103a05160018111614f365760051b61034001516402540be4006104405164012a05f20081028164012a05f200820418614f3657905004670de0b6b3a7640000810281670de0b6b3a7640000820418614f3657905004808201828110614f3657905090508155506040610460604061030060045afa506102e0516103805160018111614f365760051b6104600152610400516103a05160018111614f365760051b61046001526040610140604061046060045afa506103c051610180526103e0516101a052614324613de2565b61042051815250565b6107a0516107805114614f36576107c05115614f365761434e6108806135fc565b610880604061084060408360045afa505061436a6108c06137fb565b6108c0604061088060408360045afa505060406040604061084060045afa5060406080604061088060045afa506143a261090061394d565b61090060406108c060408360045afa505061078051610320527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610340526107c051610360526107605161038052610820516103a0525f6103c0526144086109206131f3565b61092051610900526107805160018111614f365760051b6108c00151670de0b6b3a7640000610900516107805160018111614f365760051b6108400151808202811583838304141715614f36579050905004808201828110614f36579050905061092052610920516102e052604061030060406108c060045afa506040610340604061084060045afa5061078051610380526107a0516103a0526144ad610960613f75565b61096051610940526107e05161094051101561454d57602e610960527f45786368616e676520726573756c74656420696e20666577657220636f696e73610980527f207468616e2065787065637465640000000000000000000000000000000000006109a05261096050610960518061098001601f825f031636823750506308c379a061092052602061094052601f19601f61096051011660440161093cfd5b6107a051604052610940516060526108005160805261456a61342c565b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd97140610780516109605261090051610980526107a0516109a052610940516109c0526080610960a261094051815250565b60406040604061012060045afa5060406080604061016060045afa506145e261020061394d565b61020060406101c060408360045afa505060206152be5f395f516350e7277d610200526060806102205280610220015f6101c0516103c0526101e0516103e05260026103a0525f6103a0518084528060051b5f8260088111614f3657801561466457905b8060051b6103c001518160051b602089010152600101818118614646575b5050820160200191505090509050810190506101a0516102405260026102605250602061020061018461021c845afa61469f573d5f5f3e3d5ffd5b60203d10614f3657610200905051815250565b6146bd6102606139cf565b61026051610240526146d06102a06135fc565b6102a0604061026060408360045afa50506040610360604061026060045afa506146fb6102e06137fb565b6102e060406103a060408360045afa505060806040608061036060045afa5061472561032061394d565b61032060406102a060408360045afa505060206152be5f395f516350e7277d610300526060806103205280610320015f6102a0516104c0526102c0516104e05260026104a0525f6104a0518084528060051b5f8260088111614f365780156147a757905b8060051b6104c001518160051b602089010152600101818118614789575b505082016020019150509050905081019050610240516103405260026103605250602061030061018461031c845afa6147e2573d5f5f3e3d5ffd5b60203d10614f36576103009050516102e052601954610300526102e051610200516102e051808202811583838304141715614f365790509050610300518015614f365780820490509050808203828111614f3657905090506103205260206152be5f395f51637982c3406103605260a06102405161038052610220516103a052806103c05280610380015f6102a051610560526102c051610580526002610540525f610540518084528060051b5f8260088111614f365780156148bf57905b8060051b61056001518160051b6020890101526001018181186148a1575b505082016020019150509050905081019050610320516103e0526002610400525060206103606101c461037c845afa6148fa573d5f5f3e3d5ffd5b60203d10614f36576103609050516103405260035460011b60021c61036052604061038060406102a060045afa506102e05161032051808201828110614f36579050905060021c6103c0526080366103e0375f6002905b80610460525f6103e0526104605160018111614f365760051b6102a00151610400526102205161046051186149e5576104005161032051808202811583838304141715614f3657905090506102e0518015614f36578082049050905061034051808203828111614f3657905090506103e0526104005161034051808201828110614f36579050905060011c61042052614a31565b610400516104005161032051808202811583838304141715614f3657905090506102e0518015614f365780820490509050808203828111614f3657905090506103e05261040051610420525b610420516040526103c05160605261036051608052614a51610480613ada565b6104805161044052610400516402540be400610440516103e051808202811583838304141715614f36579050905004808203828111614f3657905090506104605160018111614f365760051b61038001526001018181186149515750506102205160018111614f365760051b610380015160206152be5f395f51637982c3406104805260a0610240516104a052610220516104c052806104e052806104a0015f61038051610680526103a0516106a0526002610660525f610660518084528060051b5f8260088111614f36578015614b4357905b8060051b61068001518160051b602089010152600101818118614b25575b50508201602001915050905090508101905061032051610500526002610520525060206104806101c461049c845afa614b7e573d5f5f3e3d5ffd5b60203d10614f3657610480905051808203828111614f365790509050610460526102205160018111614f365760051b6102a0015161034051808203828111614f365790509050670de0b6b3a7640000810281670de0b6b3a7640000820418614f365790506102205160018111614f365760051b61026001518015614f365780820490509050610480526102205160018111614f365760051b61026001516104605160018103818111614f36579050670de0b6b3a7640000810281670de0b6b3a7640000820418614f365790500461046052610340516102205160018111614f365760051b6102a001526104605181526104805161046051808203828111614f36579050905060208201526040810160408160406102a060045afa50506102405160808201526103205160a082015250565b601954606051808203828111614f36579050905060195560176040516020525f5260405f208054606051808203828111614f3657905090508155505f6040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60605160805260206080a3565b60206152de5f395f5163cab4d3db610160526020610160600461017c845afa614d47573d5f5f3e3d5ffd5b60203d10614f3657610160518060a01c614f36576101a0526101a09050516101405261014051614d7657614e25565b60095460208160051b015f81601f0160051c60098111614f36578015614db157905b80600901548160051b6101600152600101818118614d98575b505050505f6002905b80610280526102805161016051811015614f365760051b610180015115614e0b57610280516040526102805161016051811015614f365760051b610180015160605261014051608052614e0b61342c565b600101818118614dba5750505f600a555f600b5560026009555b565b602061559e5f395f514614614eaf577fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472606052602061557e6080397f1c54f243822e0e9a0a377610b81577e771b3efe79964e76636b0d5d10247950d60a0524660c0523060e05260206155be6101003960c06040526040805160208201209050815250614eb8565b60206155de8239505b565b60176040516020525f5260405f208054608051808203828111614f36579050905081555060176060516020525f5260405f208054608051808201828110614f3657905090508155506060516040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60805160a052602060a0a3565b5f80fd06294f620a00814fd2090073509d0604dc50500b002b510d07054450c70a000d4fa8060202501109bb7b8b8027310514052288012a057e3db030039f85f446c1d0299705015c28382dad457ecebe0002e22529357750006705551a65882d0b0554fd4d50020b0576a2f0f029b00576a9cd3e2b0845a6417ed604368544ee19860440a571511a5e007205dd62ed3e029f45d52d5b86008e250e71d1b924e66514f0597929e40570a08231027925fee3f7f900f7054903b0d129c0253da575a1008005fd0684b12a760595d89b4101ba051ddc3b01016805313ce56702000507211ef7263e65cc2b27d726ea455e0d443f2592653eb1719f198c85c661065700b6258edfdd5f00eb0590d208371d7625d505accf20fde5687276531ef425db1bb01b19a6a565bbea6b2e6845bfa0b133030805ddca3f4300df05ed8e84f328a265095ea7b320954506fdde03017405e3103273133f65a9059cbb1f6a45907a016b1f3a051a4d01d21147653931ab521d5125ec0238621d8c25afb4301203a9a55409491a01060567df02ca243a650b4c7e4d09646523b872dd1f9b6530c540851d47051be913a50150053644e515242805b4b577ad01120552d2cfdd134985081579a511518518160ddd271c05ddc1f59d0320a53c157e642bad450c3e4b54096e855b36389c197c653df021240316852081066c011e05e2e7d2640136259c4258c4015c05000000000000000000000000a5588f7cdf560811710a2d82d3c9c99769db1dcb000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000853d955acef822db058eb8505911ed77f175b99e0000000000000000000000006c3ea9036406852006290770bedfcaba0e23a0e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9cbc565a9f4120a2740ec6f64cc24aeb2bb3e5e0000000000000000000000006a8cbed756804b16e05e741edabd5cb544ae21bf0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000a5588f7cdf560811710a2d82d3c9c99769db1dcb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e444f4c412f46524158505955534400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007637276444f4c4100000000000000000000000000000000000000000000000000ca347bf26e7a8947b458bf8f5178d369f93c85d199bb7c0df961f4356a73643000000000000000000000000000000000000000000000000000000000000000017ae47733cb63a92e66daa4f66c551430b23024ed5a6a684d5ae4dd57337c94b1e1fabe1352b66b5fd417b2e49f569398f6fdfee0e2f26ee8de971751334a39cc` + bytecode, _ := hex.DecodeString(bytecodeStr) + + expSelectors := []string{ + "06fdde03", // name() + "07211ef7", // get_dy_underlying(int128,int128,uint256) + "081579a5", // remove_liquidity_one_coin(uint256,int128,uint256,address) + "095ea7b3", // approve(address,uint256) + "0b4c7e4d", // add_liquidity(uint256[2],uint256) + "0c3e4b54", // add_liquidity(uint256[2],uint256,address) + "0e71d1b9", // get_dx_underlying(int128,int128,uint256) + "14052288", // future_A_time() + "14f05979", // get_balances() + "18160ddd", // totalSupply() + "1a4d01d2", // remove_liquidity_one_coin(uint256,int128,uint256) + "1be913a5", // ma_exp_time() + "1ddc3b01", // ma_last_time() + "2081066c", // initial_A_time() + "23b872dd", // transferFrom(address,address,uint256) + "29357750", // N_COINS() + "30c54085", // withdraw_admin_fees() + "313ce567", // decimals() + "3644e515", // DOMAIN_SEPARATOR() + "3c157e64", // ramp_A(uint256,uint256) + "3da575a1", // BASE_N_COINS() + "3df02124", // exchange(int128,int128,uint256,uint256) + "3eb1719f", // remove_liquidity(uint256,uint256[2],address) + "44ee1986", // exchange_underlying(int128,int128,uint256,uint256,address) + "4903b0d1", // balances(uint256) + "52d2cfdd", // remove_liquidity_imbalance(uint256[2],uint256,address) + "5409491a", // initial_A() + "54fd4d50", // version() + "551a6588", // stop_ramp_A() + "5b36389c", // remove_liquidity(uint256,uint256[2]) + "5e0d443f", // get_dy(int128,int128,uint256) + "67df02ca", // get_dx(int128,int128,uint256) + "68727653", // price_oracle(uint256) + "70a08231", // balanceOf(address) + "71511a5e", // BASE_POOL() + "76a2f0f0", // A_precise() + "76a9cd3e", // dynamic_fee(int128,int128) + "7e3db030", // exchange_received(int128,int128,uint256,uint256) + "7ecebe00", // nonces(address) + "8edfdd5f", // offpeg_fee_multiplier() + "95d89b41", // symbol() + "a6417ed6", // exchange_underlying(int128,int128,uint256,uint256) + "a9059cbb", // transfer(address,uint256) + "b4b577ad", // future_A() + "bb7b8b80", // get_virtual_price() + "bfa0b133", // salt() + "c6610657", // coins(uint256) + "cc2b27d7", // calc_withdraw_one_coin(uint256,int128) + "d505accf", // permit(address,address,uint256,uint256,uint8,bytes32,bytes32) + "d52d5b86", // BASE_COINS(uint256) + "dd62ed3e", // allowance(address,address) + "ddc1f59d", // exchange(int128,int128,uint256,uint256,address) + "ddca3f43", // fee() + "e2e7d264", // admin_balances(uint256) + "e3103273", // remove_liquidity_imbalance(uint256[2],uint256) + "ed8e84f3", // calc_token_amount(uint256[2],bool) + "f446c1d0", // A() + "fd0684b1", // stored_rates() + "fee3f7f9", // admin_fee() + } + + selectors, err := evmole.FunctionSelectors(context.Background(), bytecode) + if err != nil { + t.Fatalf("running function selectors: %v", err) + } + + for _, expSel := range expSelectors { + s, _ := hex.DecodeString(expSel) + found := false + for _, sel := range selectors { + if bytes.Equal(sel[:], s) { + found = true + break + } + } + + if !found { + t.Errorf("could not find selector %s", expSel) + } + } +} diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..84c1ba2 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,5 @@ +module github.com/cdump/evmole/go + +go 1.22.5 + +require github.com/tetratelabs/wazero v1.7.3 diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 0000000..b9dbbc9 --- /dev/null +++ b/go/go.sum @@ -0,0 +1,2 @@ +github.com/tetratelabs/wazero v1.7.3 h1:PBH5KVahrt3S2AHgEjKu4u+LlDbbk+nsGE3KLucy6Rw= +github.com/tetratelabs/wazero v1.7.3/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y= diff --git a/src/interface_wasm.rs b/src/interface_wasm.rs new file mode 100644 index 0000000..486560b --- /dev/null +++ b/src/interface_wasm.rs @@ -0,0 +1,30 @@ +#[no_mangle] +pub extern "C" fn function_selectors( + code_ptr: *const u8, + code_len: usize, + gas_limit: u32, + result_len_ptr: *mut u32, + result_ptr: *mut u8, + result_capacity: usize, +) -> u32 { + let code = unsafe { std::slice::from_raw_parts(code_ptr, code_len) }; + let selectors = crate::selectors::function_selectors(code, gas_limit); + + let flattened: Vec = selectors.into_iter().flatten().collect(); + let result_len = flattened.len(); + + unsafe { + *result_len_ptr = result_len as u32; + } + + if result_len > result_capacity { + // Buffer too small + return 1; + } + + unsafe { + std::ptr::copy_nonoverlapping(flattened.as_ptr(), result_ptr, result_len); + } + // Success + 0 +} diff --git a/src/lib.rs b/src/lib.rs index 7a34b01..05c5d6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,3 +21,6 @@ mod interface_py; #[cfg(feature = "javascript")] mod interface_js; + +#[cfg(feature = "wasm")] +mod interface_wasm;