Skip to content

Commit fad9f23

Browse files
authored
feat: support cairo 2.x abi (#424)
1 parent c266597 commit fad9f23

File tree

13 files changed

+12425
-3
lines changed

13 files changed

+12425
-3
lines changed

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

Lines changed: 137 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ pub enum AbiEntry {
8989
Event(AbiEvent),
9090
Struct(AbiStruct),
9191
Enum(AbiEnum),
92+
Constructor(AbiConstructor),
93+
Impl(AbiImpl),
94+
Interface(AbiInterface),
95+
L1Handler(AbiFunction),
9296
}
9397

9498
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -126,18 +130,71 @@ pub struct AbiFunction {
126130

127131
#[derive(Debug, Clone, Serialize, Deserialize)]
128132
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
129-
pub struct AbiEvent {
133+
#[serde(untagged)]
134+
pub enum AbiEvent {
135+
/// Cairo 2.x ABI event entry
136+
Typed(TypedAbiEvent),
137+
/// Cairo 1.x ABI event entry
138+
Untyped(UntypedAbiEvent),
139+
}
140+
141+
#[derive(Debug, Clone, Deserialize)]
142+
#[serde(tag = "kind", rename_all = "snake_case")]
143+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
144+
pub enum TypedAbiEvent {
145+
Struct(AbiEventStruct),
146+
Enum(AbiEventEnum),
147+
}
148+
149+
#[derive(Debug, Clone, Serialize, Deserialize)]
150+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
151+
pub struct UntypedAbiEvent {
130152
pub name: String,
131153
pub inputs: Vec<AbiNamedMember>,
132154
}
133155

156+
#[derive(Debug, Clone, Serialize, Deserialize)]
157+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
158+
pub struct AbiEventStruct {
159+
pub name: String,
160+
pub members: Vec<EventField>,
161+
}
162+
163+
#[derive(Debug, Clone, Serialize, Deserialize)]
164+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
165+
pub struct AbiEventEnum {
166+
pub name: String,
167+
pub variants: Vec<EventField>,
168+
}
169+
134170
#[derive(Debug, Clone, Serialize, Deserialize)]
135171
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
136172
pub struct AbiStruct {
137173
pub name: String,
138174
pub members: Vec<AbiNamedMember>,
139175
}
140176

177+
#[derive(Debug, Clone, Serialize, Deserialize)]
178+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
179+
pub struct AbiConstructor {
180+
pub name: String,
181+
pub inputs: Vec<AbiNamedMember>,
182+
}
183+
184+
#[derive(Debug, Clone, Serialize, Deserialize)]
185+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
186+
pub struct AbiImpl {
187+
pub name: String,
188+
pub interface_name: String,
189+
}
190+
191+
#[derive(Debug, Clone, Serialize, Deserialize)]
192+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
193+
pub struct AbiInterface {
194+
pub name: String,
195+
pub items: Vec<AbiEntry>,
196+
}
197+
141198
#[derive(Debug, Clone, Serialize, Deserialize)]
142199
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
143200
pub struct AbiEnum {
@@ -158,13 +215,29 @@ pub struct AbiOutput {
158215
pub r#type: String,
159216
}
160217

218+
#[derive(Debug, Clone, Serialize, Deserialize)]
219+
#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
220+
pub struct EventField {
221+
pub name: String,
222+
pub r#type: String,
223+
pub kind: EventFieldKind,
224+
}
225+
161226
#[derive(Debug, Clone, Serialize, Deserialize)]
162227
#[serde(rename_all = "snake_case")]
163228
pub enum StateMutability {
164229
External,
165230
View,
166231
}
167232

233+
#[derive(Debug, Clone, Serialize, Deserialize)]
234+
#[serde(rename_all = "snake_case")]
235+
pub enum EventFieldKind {
236+
Key,
237+
Data,
238+
Nested,
239+
}
240+
168241
#[derive(Debug, thiserror::Error)]
169242
pub enum ComputeClassHashError {
170243
#[error("invalid builtin name")]
@@ -370,6 +443,47 @@ impl<'de> Deserialize<'de> for PythonicHint {
370443
}
371444
}
372445

446+
// Manually implementing this so we can put `kind` in the middle:
447+
impl Serialize for TypedAbiEvent {
448+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
449+
where
450+
S: Serializer,
451+
{
452+
#[derive(Serialize)]
453+
struct StructRef<'a> {
454+
name: &'a str,
455+
kind: &'static str,
456+
members: &'a [EventField],
457+
}
458+
459+
#[derive(Serialize)]
460+
struct EnumRef<'a> {
461+
name: &'a str,
462+
kind: &'static str,
463+
variants: &'a [EventField],
464+
}
465+
466+
match self {
467+
TypedAbiEvent::Struct(inner) => StructRef::serialize(
468+
&StructRef {
469+
name: &inner.name,
470+
kind: "struct",
471+
members: &inner.members,
472+
},
473+
serializer,
474+
),
475+
TypedAbiEvent::Enum(inner) => EnumRef::serialize(
476+
&EnumRef {
477+
name: &inner.name,
478+
kind: "enum",
479+
variants: &inner.variants,
480+
},
481+
serializer,
482+
),
483+
}
484+
}
485+
}
486+
373487
fn hash_sierra_entrypoints(entrypoints: &[SierraEntryPoint]) -> FieldElement {
374488
let mut hasher = PoseidonHasher::new();
375489

@@ -394,10 +508,11 @@ mod tests {
394508
#[test]
395509
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
396510
fn test_sierra_class_deser() {
397-
// Artifacts generated from cairo v1.0.0-rc0
398511
for raw_artifact in [
399512
include_str!("../../../test-data/contracts/cairo1/artifacts/abi_types_sierra.txt"),
400513
include_str!("../../../test-data/contracts/cairo1/artifacts/erc20_sierra.txt"),
514+
include_str!("../../../test-data/contracts/cairo2/artifacts/abi_types_sierra.txt"),
515+
include_str!("../../../test-data/contracts/cairo2/artifacts/erc20_sierra.txt"),
401516
]
402517
.into_iter()
403518
{
@@ -411,10 +526,11 @@ mod tests {
411526
#[test]
412527
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
413528
fn test_compiled_class_deser() {
414-
// Artifacts generated from cairo v1.0.0-rc0
415529
for raw_artifact in [
416530
include_str!("../../../test-data/contracts/cairo1/artifacts/abi_types_compiled.txt"),
417531
include_str!("../../../test-data/contracts/cairo1/artifacts/erc20_compiled.txt"),
532+
include_str!("../../../test-data/contracts/cairo2/artifacts/abi_types_compiled.txt"),
533+
include_str!("../../../test-data/contracts/cairo2/artifacts/erc20_compiled.txt"),
418534
]
419535
.into_iter()
420536
{
@@ -448,6 +564,14 @@ mod tests {
448564
include_str!("../../../test-data/contracts/cairo1/artifacts/abi_types_sierra.txt"),
449565
include_str!("../../../test-data/contracts/cairo1/artifacts/abi_types.hashes.json"),
450566
),
567+
(
568+
include_str!("../../../test-data/contracts/cairo2/artifacts/erc20_sierra.txt"),
569+
include_str!("../../../test-data/contracts/cairo2/artifacts/erc20.hashes.json"),
570+
),
571+
(
572+
include_str!("../../../test-data/contracts/cairo2/artifacts/abi_types_sierra.txt"),
573+
include_str!("../../../test-data/contracts/cairo2/artifacts/abi_types.hashes.json"),
574+
),
451575
]
452576
.into_iter()
453577
{
@@ -475,6 +599,16 @@ mod tests {
475599
),
476600
include_str!("../../../test-data/contracts/cairo1/artifacts/abi_types.hashes.json"),
477601
),
602+
(
603+
include_str!("../../../test-data/contracts/cairo2/artifacts/erc20_compiled.txt"),
604+
include_str!("../../../test-data/contracts/cairo2/artifacts/erc20.hashes.json"),
605+
),
606+
(
607+
include_str!(
608+
"../../../test-data/contracts/cairo2/artifacts/abi_types_compiled.txt"
609+
),
610+
include_str!("../../../test-data/contracts/cairo2/artifacts/abi_types.hashes.json"),
611+
),
478612
]
479613
.into_iter()
480614
{
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"sierra_class_hash": "0x61ec4af0e7b12eda8f79d7dc20014f6bba883938a16c1a10d300e88e38ff255",
3+
"compiled_class_hash": "0x6a1254307a13eb075103df104e7055f3f61e3a7de3afa2acae77a4acc102de4"
4+
}

0 commit comments

Comments
 (0)