diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ff2dfcbe4c..204e96a7a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -107,7 +107,7 @@ jobs: SEED: 0 codecov: - runs-on: starkware-ubuntu-latest-medium + runs-on: starkware-ubuntu-latest-large steps: - uses: actions/checkout@v4 with: diff --git a/Cargo.lock b/Cargo.lock index 83e57f621d..362d0fc370 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,10 +93,11 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-chains" -version = "0.1.36" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94c225801d42099570d0674701dddd4142f0ef715282aeb5985042e2ec962df7" +checksum = "156bfc5dcd52ef9a5f33381701fa03310317e14c65093a9430d3e3557b08dcd3" dependencies = [ + "alloy-primitives", "num_enum", "strum 0.26.3", ] @@ -137,9 +138,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1109c57718022ac84c194f775977a534e1b3969b405e55693a61c42187cc0612" +checksum = "f95d76a38cae906fd394a5afb0736aaceee5432efe76addfd71048e623e208af" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -194,9 +195,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cc0e59c803dd44d14fc0cfa9fea1f74cfa8fd9fb60ca303ced390c58c28d4e" +checksum = "03c66eec1acdd96b39b995b8f5ee5239bc0c871d62c527ae1ac9fd1d7fecd455" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -253,9 +254,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a289ffd7448036f2f436b377f981c79ce0b2090877bad938d43387dc09931877" +checksum = "8ecb848c43f6b06ae3de2e4a67496cbbabd78ae87db0f1248934f15d76192c6a" dependencies = [ "alloy-rlp", "bytes", @@ -404,9 +405,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0409e3ba5d1de409997a7db8b8e9d679d52088c1dee042a85033affd3cadeab4" +checksum = "661c516eb1fa3294cc7f2fb8955b3b609d639c282ac81a4eedb14d3046db503a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -418,9 +419,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18372ef450d59f74c7a64a738f546ba82c92f816597fed1802ef559304c81f1" +checksum = "ecbabb8fc3d75a0c2cea5215be22e7a267e3efde835b0f2a8922f5e3f5d47683" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -436,9 +437,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7bad89dd0d5f109e8feeaf787a9ed7a05a91a9a0efc6687d147a70ebca8eff7" +checksum = "16517f2af03064485150d89746b8ffdcdbc9b6eeb3d536fb66efd7c2846fbc75" dependencies = [ "const-hex", "dunce", @@ -451,9 +452,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd3548d5262867c2c4be6223fe4f2583e21ade0ca1c307fd23bc7f28fca479e" +checksum = "c07ebb0c1674ff8cbb08378d7c2e0e27919d2a2dae07ad3bca26174deda8d389" dependencies = [ "serde", "winnow 0.6.20", @@ -461,9 +462,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa666f1036341b46625e72bd36878bf45ad0185f1b88601223e1ec6ed4b72b1" +checksum = "8e448d879903624863f608c552d10efb0e0905ddbee98b0049412799911eb062" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -891,9 +892,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e614738943d3f68c628ae3dbce7c3daffb196665f82f8c8ea6b65de73c79429" +checksum = "e26a9844c659a2a293d239c7910b752f8487fe122c6c8bd1659bf85a6507c302" dependencies = [ "flate2", "futures-core", @@ -1370,9 +1371,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags 2.6.0", "cexpr", @@ -2381,9 +2382,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.28" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", @@ -2501,9 +2502,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -2511,9 +2512,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -3138,18 +3139,18 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling 0.20.10", "proc-macro2", @@ -3159,9 +3160,9 @@ dependencies = [ [[package]] name = "derive_builder_macro" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", "syn 2.0.79", @@ -5310,9 +5311,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -6485,7 +6486,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b1b5806a63bc959cd5c4e5db8cadd20e40045d41969d325132748db8af11b7f" dependencies = [ - "bindgen 0.69.4", + "bindgen 0.69.5", ] [[package]] @@ -10681,9 +10682,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a850d65181df41b83c6be01a7d91f5e9377c43d48faa5af7d95816f437f5a3" +checksum = "20e7b52ad118b2153644eea95c6fc740b6c1555b2344fdab763fc9de4075f665" dependencies = [ "paste", "proc-macro2", @@ -10782,7 +10783,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae726d43658a13a9cd479de814be1311fea69236cd821e931a4fb9ca4d70e50" dependencies = [ - "bindgen 0.69.4", + "bindgen 0.69.5", "cc", "paste", "thiserror", @@ -11712,9 +11713,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -11723,9 +11724,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -11738,9 +11739,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -11750,9 +11751,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11760,9 +11761,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -11773,15 +11774,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/crates/blockifier/src/execution/errors.rs b/crates/blockifier/src/execution/errors.rs index ab867ff320..b8222d1a7a 100644 --- a/crates/blockifier/src/execution/errors.rs +++ b/crates/blockifier/src/execution/errors.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; +use cairo_native::error::Error as NativeError; use cairo_vm::types::builtin_name::BuiltinName; use cairo_vm::types::errors::math_errors::MathError; use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; @@ -88,6 +89,8 @@ pub enum EntryPointExecutionError { #[error("Invalid input: {input_descriptor}; {info}")] InvalidExecutionInput { input_descriptor: String, info: String }, #[error(transparent)] + NativeUnexpectedError(#[from] NativeError), + #[error(transparent)] PostExecutionError(#[from] PostExecutionError), #[error(transparent)] PreExecutionError(#[from] PreExecutionError), diff --git a/crates/blockifier/src/execution/execution_utils.rs b/crates/blockifier/src/execution/execution_utils.rs index 1cb387041f..5b8e78089f 100644 --- a/crates/blockifier/src/execution/execution_utils.rs +++ b/crates/blockifier/src/execution/execution_utils.rs @@ -21,18 +21,18 @@ use starknet_api::deprecated_contract_class::Program as DeprecatedProgram; use starknet_api::transaction::Calldata; use starknet_types_core::felt::Felt; -use super::entry_point::ConstructorEntryPointExecutionResult; -use super::errors::ConstructorEntryPointExecutionError; use crate::execution::call_info::{CallInfo, Retdata}; use crate::execution::contract_class::{ContractClass, TrackedResource}; use crate::execution::entry_point::{ execute_constructor_entry_point, CallEntryPoint, ConstructorContext, + ConstructorEntryPointExecutionResult, EntryPointExecutionContext, EntryPointExecutionResult, }; -use crate::execution::errors::PostExecutionError; +use crate::execution::errors::{ConstructorEntryPointExecutionError, PostExecutionError}; +use crate::execution::native::entry_point_execution as native_entry_point_execution; use crate::execution::{deprecated_entry_point_execution, entry_point_execution}; use crate::state::errors::StateError; use crate::state::state_api::State; @@ -107,8 +107,14 @@ pub fn execute_entry_point_call( resources, context, ), - ContractClass::V1Native(_contract_class) => { - unimplemented!("Native contract entry point execution is not yet implemented.") + ContractClass::V1Native(contract_class) => { + native_entry_point_execution::execute_entry_point_call( + call, + contract_class, + state, + resources, + context, + ) } } } diff --git a/crates/blockifier/src/execution/native.rs b/crates/blockifier/src/execution/native.rs index 7c3dd35b21..b5d4461247 100644 --- a/crates/blockifier/src/execution/native.rs +++ b/crates/blockifier/src/execution/native.rs @@ -1,3 +1,4 @@ +pub mod entry_point_execution; pub mod syscall_handler; pub mod utils; diff --git a/crates/blockifier/src/execution/native/entry_point_execution.rs b/crates/blockifier/src/execution/native/entry_point_execution.rs new file mode 100644 index 0000000000..38e64fffbb --- /dev/null +++ b/crates/blockifier/src/execution/native/entry_point_execution.rs @@ -0,0 +1,96 @@ +use cairo_native::execution_result::ContractExecutionResult; +use cairo_vm::vm::runners::cairo_runner::ExecutionResources; +use num_traits::ToPrimitive; + +use crate::execution::call_info::{CallExecution, CallInfo, Retdata}; +use crate::execution::contract_class::{NativeContractClassV1, TrackedResource}; +use crate::execution::entry_point::{ + CallEntryPoint, + EntryPointExecutionContext, + EntryPointExecutionResult, +}; +use crate::execution::errors::{EntryPointExecutionError, PostExecutionError}; +use crate::execution::native::syscall_handler::NativeSyscallHandler; +use crate::state::state_api::State; + +pub fn execute_entry_point_call( + call: CallEntryPoint, + contract_class: NativeContractClassV1, + state: &mut dyn State, + resources: &mut ExecutionResources, + context: &mut EntryPointExecutionContext, +) -> EntryPointExecutionResult { + let function_id = contract_class.get_entry_point(&call)?; + + let mut syscall_handler: NativeSyscallHandler<'_> = NativeSyscallHandler::new( + state, + call.caller_address, + call.storage_address, + call.entry_point_selector, + resources, + context, + ); + + let execution_result = contract_class.executor.invoke_contract_dynamic( + &function_id, + &call.calldata.0, + Some(call.initial_gas.into()), + &mut syscall_handler, + ); + + let call_result = match execution_result { + Err(runner_err) => Err(EntryPointExecutionError::NativeUnexpectedError(runner_err)), + Ok(res) + if res.failure_flag + && !syscall_handler.context.versioned_constants().enable_reverts => + { + Err(EntryPointExecutionError::ExecutionFailed { error_data: res.return_values }) + } + Ok(res) => Ok(res), + }?; + + create_callinfo(call, call_result, syscall_handler) +} + +fn create_callinfo( + call: CallEntryPoint, + call_result: ContractExecutionResult, + syscall_handler: NativeSyscallHandler<'_>, +) -> Result { + let remaining_gas = + call_result.remaining_gas.to_u64().ok_or(PostExecutionError::MalformedReturnData { + error_message: format!( + "Unexpected remaining gas. Gas value is bigger than u64: {}", + call_result.remaining_gas + ), + })?; + if remaining_gas > call.initial_gas { + return Err(PostExecutionError::MalformedReturnData { + error_message: format!( + "Unexpected remaining gas. Used gas is greater than initial gas: {} > {}", + remaining_gas, call.initial_gas + ), + } + .into()); + } + + let gas_consumed = call.initial_gas - remaining_gas; + + Ok(CallInfo { + call, + execution: CallExecution { + retdata: Retdata(call_result.return_values), + events: syscall_handler.events, + l2_to_l1_messages: syscall_handler.l2_to_l1_messages, + failed: call_result.failure_flag, + gas_consumed, + }, + // todo(rodrigo): execution resources rely heavily on how the VM work, therefore + // the dummy values + resources: ExecutionResources::default(), + inner_calls: syscall_handler.inner_calls, + storage_read_values: syscall_handler.read_values, + accessed_storage_keys: syscall_handler.accessed_keys, + tracked_resource: TrackedResource::SierraGas, + }) +} diff --git a/crates/blockifier/src/execution/native/utils.rs b/crates/blockifier/src/execution/native/utils.rs index 2aeb969e9d..87f53f4795 100644 --- a/crates/blockifier/src/execution/native/utils.rs +++ b/crates/blockifier/src/execution/native/utils.rs @@ -1,5 +1,4 @@ use cairo_lang_starknet_classes::contract_class::ContractEntryPoint; -use itertools::Itertools; use starknet_api::core::EntryPointSelector; use starknet_types_core::felt::Felt; @@ -21,28 +20,3 @@ pub fn encode_str_as_felts(msg: &str) -> Vec { } encoding } - -// Todo(rodrigo): This is an opinionated way of interpretting error messages. It's ok for now but I -// think it can be improved; (for example) trying to make the output similar to a Cairo VM panic -pub fn decode_felts_as_str(encoding: &[Felt]) -> String { - let bytes_err: Vec<_> = - encoding.iter().flat_map(|felt| felt.to_bytes_be()[1..32].to_vec()).collect(); - - match String::from_utf8(bytes_err) { - // If the string is utf8 make sure it is not prefixed by no null chars. Null chars in - // between can still happen - Ok(s) => s.trim_matches('\0').to_owned(), - // If the string is non-utf8 overall, try to decode them as utf8 chunks of it and keep the - // original bytes for the non-utf8 chunks - Err(_) => { - let err_msgs = encoding - .iter() - .map(|felt| match String::from_utf8(felt.to_bytes_be()[1..32].to_vec()) { - Ok(s) => format!("{} ({})", s.trim_matches('\0'), felt), - Err(_) => felt.to_string(), - }) - .join(", "); - format!("[{}]", err_msgs) - } - } -} diff --git a/crates/blockifier/src/execution/native/utils_test.rs b/crates/blockifier/src/execution/native/utils_test.rs index bffd39b6ca..553409e251 100644 --- a/crates/blockifier/src/execution/native/utils_test.rs +++ b/crates/blockifier/src/execution/native/utils_test.rs @@ -2,11 +2,11 @@ use cairo_lang_starknet_classes::contract_class::ContractEntryPoint; use num_bigint::BigUint; use pretty_assertions::assert_eq; use starknet_api::core::EntryPointSelector; +use starknet_api::execution_utils::format_panic_data; use starknet_types_core::felt::Felt; use crate::execution::native::utils::{ contract_entrypoint_to_entrypoint_selector, - decode_felts_as_str, encode_str_as_felts, }; @@ -22,23 +22,33 @@ fn test_contract_entrypoint_to_entrypoint_selector() { } #[test] -fn test_encode_decode_str() { - const STR: &str = "normal utf8 string:"; +fn test_encode_small_str() { + const STR: &str = "I fit in a felt :)"; let encoded_felt_array = encode_str_as_felts(STR); - let decoded_felt_array = decode_felts_as_str(encoded_felt_array.as_slice()); + let decoded_felt_array = format_panic_data(&encoded_felt_array); - assert_eq!(&decoded_felt_array, STR); + assert_eq!( + &decoded_felt_array, + "0x492066697420696e20612066656c74203a2900000000000000000000000000 ('I fit in a felt :)')" + ); } #[test] -fn test_decode_non_utf8_str() { - let v1 = Felt::from_dec_str("1234").unwrap(); - let v2_msg = "i am utf8"; - let v2 = Felt::from_bytes_be_slice(v2_msg.as_bytes()); - let v3 = Felt::from_dec_str("13299428").unwrap(); - let felts = [v1, v2, v3]; - - assert_eq!(decode_felts_as_str(&felts), format!("[{}, {} ({}), {}]", v1, v2_msg, v2, v3)) +fn test_encode_large_str() { + const STR: &str = + "Three sad tigers ate wheat. Two tigers were full. The other tiger not so much"; + + let encoded_felt_array = encode_str_as_felts(STR); + + let decoded_felt_array = format_panic_data(&encoded_felt_array); + + assert_eq!( + &decoded_felt_array, + "(0x54687265652073616420746967657273206174652077686561742e2054776f ('Three sad tigers ate \ + wheat. Two'), 0x2074696765727320776572652066756c6c2e20546865206f74686572207469 (' tigers \ + were full. The other ti'), \ + 0x676572206e6f7420736f206d75636800000000000000000000000000000000 ('ger not so much'))" + ); }