Skip to content

Commit a9e65a3

Browse files
authored
feat(torii): indexing cartridge controllers (#2959)
* feat(torii): indexing cartridge controllers & cartrdige paymaster contracts * processor and migration * rename * use adderss for paralle * fmt * use udc to retrieve events * read paymaster accounts * use cartridge magic instead of deployer address * comments * c * logs * chore * format address in hex * unused event id * rename * fix build
1 parent f4b733d commit a9e65a3

File tree

16 files changed

+208
-12
lines changed

16 files changed

+208
-12
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/torii/cli/src/options.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,15 @@ pub struct IndexingOptions {
171171
#[serde(default)]
172172
pub world_block: u64,
173173

174+
/// Whether or not to index Cartridge controllers.
175+
#[arg(
176+
long = "indexing.controllers",
177+
default_value_t = false,
178+
help = "Whether or not to index Cartridge controllers."
179+
)]
180+
#[serde(default)]
181+
pub controllers: bool,
182+
174183
/// Whether or not to read models from the block number they were registered in.
175184
/// If false, models will be read from the latest block.
176185
#[arg(
@@ -194,6 +203,7 @@ impl Default for IndexingOptions {
194203
max_concurrent_tasks: DEFAULT_MAX_CONCURRENT_TASKS,
195204
namespaces: vec![],
196205
world_block: 0,
206+
controllers: false,
197207
strict_model_reader: false,
198208
}
199209
}
@@ -238,6 +248,10 @@ impl IndexingOptions {
238248
self.world_block = other.world_block;
239249
}
240250

251+
if !self.controllers {
252+
self.controllers = other.controllers;
253+
}
254+
241255
if !self.strict_model_reader {
242256
self.strict_model_reader = other.strict_model_reader;
243257
}

crates/torii/indexer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ ipfs-api-backend-hyper.workspace = true
3838
tokio-util.workspace = true
3939
tracing.workspace = true
4040
torii-sqlite.workspace = true
41+
lazy_static.workspace = true
4142

4243
[dev-dependencies]
4344
dojo-test-utils.workspace = true

crates/torii/indexer/src/engine.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use torii_sqlite::{Cursors, Sql};
2828
use tracing::{debug, error, info, trace, warn};
2929

3030
use crate::constants::LOG_TARGET;
31+
use crate::processors::controller::ControllerProcessor;
3132
use crate::processors::erc20_legacy_transfer::Erc20LegacyTransferProcessor;
3233
use crate::processors::erc20_transfer::Erc20TransferProcessor;
3334
use crate::processors::erc721_legacy_transfer::Erc721LegacyTransferProcessor;
@@ -39,6 +40,7 @@ use crate::processors::register_event::RegisterEventProcessor;
3940
use crate::processors::register_model::RegisterModelProcessor;
4041
use crate::processors::store_del_record::StoreDelRecordProcessor;
4142
use crate::processors::store_set_record::StoreSetRecordProcessor;
43+
use crate::processors::store_transaction::StoreTransactionProcessor;
4244
use crate::processors::store_update_member::StoreUpdateMemberProcessor;
4345
use crate::processors::store_update_record::StoreUpdateRecordProcessor;
4446
use crate::processors::upgrade_event::UpgradeEventProcessor;
@@ -62,7 +64,7 @@ impl<P: Provider + Send + Sync + std::fmt::Debug + 'static> Default for Processo
6264
fn default() -> Self {
6365
Self {
6466
block: vec![],
65-
transaction: vec![],
67+
transaction: vec![Box::new(StoreTransactionProcessor)],
6668
// We shouldn't have a catch all for now since the world doesn't forward raw events
6769
// anymore.
6870
catch_all_event: Box::new(RawEventProcessor) as Box<dyn EventProcessor<P>>,
@@ -105,6 +107,7 @@ impl<P: Provider + Send + Sync + std::fmt::Debug + 'static> Processors<P> {
105107
Box::new(Erc721LegacyTransferProcessor) as Box<dyn EventProcessor<P>>,
106108
],
107109
),
110+
(ContractType::UDC, vec![Box::new(ControllerProcessor) as Box<dyn EventProcessor<P>>]),
108111
];
109112

110113
for (contract_type, processors) in event_processors {
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
use std::hash::{DefaultHasher, Hash, Hasher};
2+
3+
use anyhow::{Error, Result};
4+
use async_trait::async_trait;
5+
use dojo_world::contracts::world::WorldContractReader;
6+
use lazy_static::lazy_static;
7+
use starknet::core::types::Event;
8+
use starknet::core::utils::parse_cairo_short_string;
9+
use starknet::macros::felt;
10+
use starknet::providers::Provider;
11+
use starknet_crypto::Felt;
12+
use torii_sqlite::Sql;
13+
use tracing::info;
14+
15+
use super::{EventProcessor, EventProcessorConfig};
16+
use crate::task_manager::{TaskId, TaskPriority};
17+
18+
pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::controller";
19+
20+
#[derive(Default, Debug)]
21+
pub struct ControllerProcessor;
22+
23+
lazy_static! {
24+
// https://x.cartridge.gg/
25+
pub(crate) static ref CARTRIDGE_MAGIC: [Felt; 22] = [
26+
felt!("0x68"),
27+
felt!("0x74"),
28+
felt!("0x74"),
29+
felt!("0x70"),
30+
felt!("0x73"),
31+
felt!("0x3a"),
32+
felt!("0x2f"),
33+
felt!("0x2f"),
34+
felt!("0x78"),
35+
felt!("0x2e"),
36+
felt!("0x63"),
37+
felt!("0x61"),
38+
felt!("0x72"),
39+
felt!("0x74"),
40+
felt!("0x72"),
41+
felt!("0x69"),
42+
felt!("0x64"),
43+
felt!("0x67"),
44+
felt!("0x65"),
45+
felt!("0x2e"),
46+
felt!("0x67"),
47+
felt!("0x67"),
48+
];
49+
}
50+
51+
#[async_trait]
52+
impl<P> EventProcessor<P> for ControllerProcessor
53+
where
54+
P: Provider + Send + Sync + std::fmt::Debug,
55+
{
56+
fn event_key(&self) -> String {
57+
"ContractDeployed".to_string()
58+
}
59+
60+
fn validate(&self, event: &Event) -> bool {
61+
// ContractDeployed event has no keys and contains username in data
62+
event.keys.len() == 1 && !event.data.is_empty()
63+
}
64+
65+
fn task_priority(&self) -> TaskPriority {
66+
3
67+
}
68+
69+
fn task_identifier(&self, event: &Event) -> TaskId {
70+
let mut hasher = DefaultHasher::new();
71+
// the contract address is the first felt in data
72+
event.data[0].hash(&mut hasher);
73+
hasher.finish()
74+
}
75+
76+
async fn process(
77+
&self,
78+
_world: &WorldContractReader<P>,
79+
db: &mut Sql,
80+
_block_number: u64,
81+
block_timestamp: u64,
82+
_event_id: &str,
83+
event: &Event,
84+
_config: &EventProcessorConfig,
85+
) -> Result<(), Error> {
86+
// Address is the first felt in data
87+
let address = event.data[0];
88+
89+
let calldata = event.data[5..].to_vec();
90+
// our calldata has to be more than 25 felts.
91+
if calldata.len() < 25 {
92+
return Ok(());
93+
}
94+
// check for this sequence of felts
95+
let cartridge_magic_len = calldata[2];
96+
// length has to be 22
97+
if cartridge_magic_len != Felt::from(22) {
98+
return Ok(());
99+
}
100+
101+
// this should never fail if since our len is 22
102+
let cartridge_magic: [Felt; 22] = calldata[3..25].try_into().unwrap();
103+
104+
// has to match with https://x.cartridge.gg/
105+
if !CARTRIDGE_MAGIC.eq(&cartridge_magic) {
106+
return Ok(());
107+
}
108+
109+
// Last felt in data is the salt which is the username encoded as short string
110+
let username_felt = event.data[event.data.len() - 1];
111+
let username = parse_cairo_short_string(&username_felt)?;
112+
113+
info!(
114+
target: LOG_TARGET,
115+
username = %username,
116+
address = %format!("{address:#x}"),
117+
"Controller deployed."
118+
);
119+
120+
db.add_controller(&username, &format!("{address:#x}"), block_timestamp).await?;
121+
122+
Ok(())
123+
}
124+
}

crates/torii/indexer/src/processors/erc20_legacy_transfer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ where
8383
block_number,
8484
)
8585
.await?;
86-
debug!(target: LOG_TARGET,from = ?from, to = ?to, value = ?value, "Legacy ERC20 Transfer");
86+
debug!(target: LOG_TARGET,from = ?from, to = ?to, value = ?value, "Legacy ERC20 Transfer.");
8787

8888
Ok(())
8989
}

crates/torii/indexer/src/processors/erc20_transfer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ where
8383
block_number,
8484
)
8585
.await?;
86-
debug!(target: LOG_TARGET,from = ?from, to = ?to, value = ?value, "ERC20 Transfer");
86+
debug!(target: LOG_TARGET,from = ?from, to = ?to, value = ?value, "ERC20 Transfer.");
8787

8888
Ok(())
8989
}

crates/torii/indexer/src/processors/erc721_legacy_transfer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ where
9090
block_number,
9191
)
9292
.await?;
93-
debug!(target: LOG_TARGET, from = ?from, to = ?to, token_id = ?token_id, "ERC721 Transfer");
93+
debug!(target: LOG_TARGET, from = ?from, to = ?to, token_id = ?token_id, "ERC721 Transfer.");
9494

9595
Ok(())
9696
}

crates/torii/indexer/src/processors/erc721_transfer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ where
9090
block_number,
9191
)
9292
.await?;
93-
debug!(target: LOG_TARGET, from = ?from, to = ?to, token_id = ?token_id, "ERC721 Transfer");
93+
debug!(target: LOG_TARGET, from = ?from, to = ?to, token_id = ?token_id, "ERC721 Transfer.");
9494

9595
Ok(())
9696
}

crates/torii/indexer/src/processors/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use torii_sqlite::Sql;
99

1010
use crate::task_manager::{TaskId, TaskPriority};
1111

12+
pub mod controller;
1213
pub mod erc20_legacy_transfer;
1314
pub mod erc20_transfer;
1415
pub mod erc721_legacy_transfer;
@@ -25,7 +26,6 @@ pub mod store_update_member;
2526
pub mod store_update_record;
2627
pub mod upgrade_event;
2728
pub mod upgrade_model;
28-
2929
#[derive(Clone, Debug, Default)]
3030
pub struct EventProcessorConfig {
3131
pub historical_events: HashSet<String>,

0 commit comments

Comments
 (0)