Skip to content

Commit 841caac

Browse files
authored
feat: port starknet.js SNIP-12 deviations (#704)
* test: add snip-12 simple enum test case The expected hash is based on a patched version of starknet.js at: starknet-io/starknet.js#1292 * feat: port starknet.js SNIP-12 deviations
1 parent 88a96d1 commit 841caac

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

starknet-core/src/types/typed_data/mod.rs

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl TypedData {
161161
return Err(TypedDataError::UnexpectedEnum(name.to_owned()));
162162
}
163163

164-
self.encode_enum::<H>(type_hash, enum_def, obj_value)?
164+
self.encode_enum::<H>(enum_def, obj_value)?
165165
}
166166
}
167167
}
@@ -482,15 +482,20 @@ impl TypedData {
482482

483483
fn encode_enum<H>(
484484
&self,
485-
type_hash: Felt,
486485
enum_def: &EnumDefinition,
487486
value: &ObjectValue,
488487
) -> Result<Felt, TypedDataError>
489488
where
490489
H: TypedDataHasher,
491490
{
492491
let mut hasher = H::default();
493-
hasher.update(type_hash);
492+
493+
// Here we're NOT hashing the enum type hash. This is technically a SNIP-12 violation.
494+
// Unfortunately, as the de-facto standard, starknet.js implemented it incorrectly. Despite
495+
// the fix being merged (https://github.com/starknet-io/starknet.js/pull/1281) it's expected
496+
// to never be released.
497+
//
498+
// Context: https://github.com/starknet-io/starknet.js/pull/1292
494499

495500
let mut value_field_iter = value.fields.iter();
496501

@@ -878,7 +883,56 @@ mod tests {
878883

879884
#[test]
880885
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
881-
fn test_message_hash_v1_with_enum() {
886+
fn test_message_hash_v1_with_simple_enum() {
887+
let raw = r###"{
888+
"types": {
889+
"StarknetDomain": [
890+
{ "name": "name", "type": "shortstring" },
891+
{ "name": "version", "type": "shortstring" },
892+
{ "name": "chainId", "type": "shortstring" },
893+
{ "name": "revision", "type": "shortstring" }
894+
],
895+
"Example Message": [
896+
{ "name": "Value", "type": "enum", "contains": "My Enum" }
897+
],
898+
"My Enum": [
899+
{ "name": "Variant 1", "type": "()" },
900+
{ "name": "Variant 2", "type": "(string)" },
901+
{ "name": "Variant 3", "type": "(u128)" }
902+
]
903+
},
904+
"primaryType": "Example Message",
905+
"domain": {
906+
"name": "Starknet Example",
907+
"version": "1",
908+
"chainId": "SN_MAIN",
909+
"revision": "1"
910+
},
911+
"message": {
912+
"Value": {
913+
"Variant 2": ["tuple element"]
914+
}
915+
}
916+
}"###;
917+
918+
let data = serde_json::from_str::<TypedData>(raw).unwrap();
919+
920+
assert_eq!(
921+
data.message_hash(Felt::from_hex_unchecked("0x1234"))
922+
.unwrap(),
923+
// This expected hash was generated with starknet.js v6.24.0, due to the expectation
924+
// that the following fixes, despite being merged, would never be released:
925+
// - https://github.com/starknet-io/starknet.js/pull/1281
926+
// - https://github.com/starknet-io/starknet.js/pull/1288
927+
Felt::from_hex_unchecked(
928+
"0x05cb0569ef378e0c17c07c13cb86bc6e067f824ccffd79fd49d875ecc0296124"
929+
)
930+
);
931+
}
932+
933+
#[test]
934+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
935+
fn test_message_hash_v1_with_enum_nested() {
882936
let raw = r###"{
883937
"types": {
884938
"StarknetDomain": [
@@ -931,8 +985,16 @@ mod tests {
931985
assert_eq!(
932986
data.message_hash(Felt::from_hex_unchecked("0x1234"))
933987
.unwrap(),
988+
// This expected hash was generated with starknet.js v6.24.0 patched with:
989+
// - https://github.com/starknet-io/starknet.js/pull/1289
990+
//
991+
// Here a patched version is used as it's expected that the patch would eventually be
992+
// released.
993+
//
994+
// See this thread for more context:
995+
// - https://github.com/starknet-io/starknet.js/pull/1292
934996
Felt::from_hex_unchecked(
935-
"0x03745761c0f8ab5f0dbbba52b448f7db6ebfecbf74069073dcbf4fc5a6608125"
997+
"0x0470e6107a4d464e16d8f77ff673c06f6fbfe107fef1e496e53b10d3744afd42"
936998
)
937999
);
9381000
}

starknet-core/src/types/typed_data/types.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,15 @@ impl SignatureGenerator<'_> {
215215
let mut variant_iter = enum_def.variants.iter().peekable();
216216
while let Some(variant) = variant_iter.next() {
217217
Self::write_escaped_name(&variant.name, signature, revision);
218+
219+
// This is technically a SNIP-12 violation. Unfortunately, as the de-facto
220+
// standard, starknet.js implemented it incorrectly. Despite the fix being
221+
// merged (https://github.com/starknet-io/starknet.js/issues/1286) it's expected
222+
// to never be released.
223+
//
224+
// Context: https://github.com/starknet-io/starknet.js/pull/1292
225+
signature.push(':');
226+
218227
signature.push('(');
219228

220229
let mut tuple_type_iter = variant.tuple_types.iter().peekable();

0 commit comments

Comments
 (0)