Skip to content

Commit

Permalink
Add erc20_approvals dataset (#185)
Browse files Browse the repository at this point in the history
  • Loading branch information
YadominJinta authored Apr 19, 2024
1 parent 4d1e74b commit 24fc2f7
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ cryo datasets
- erc20_metadata
- erc20_supplies
- erc20_transfers
- erc20_approvals
- erc721_metadata
- erc721_transfers
- eth_calls
Expand Down
112 changes: 112 additions & 0 deletions crates/freeze/src/datasets/erc20_approvals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use crate::*;
use ethers::prelude::*;
use polars::prelude::*;

/// columns for transactions
#[cryo_to_df::to_df(Datatype::Erc20Approvals)]
#[derive(Default)]
pub struct Erc20Approvals {
n_rows: u64,
block_number: Vec<u32>,
block_hash: Vec<Option<Vec<u8>>>,
transaction_index: Vec<u32>,
log_index: Vec<u32>,
transaction_hash: Vec<Vec<u8>>,
erc20: Vec<Vec<u8>>,
from_address: Vec<Vec<u8>>,
to_address: Vec<Vec<u8>>,
value: Vec<U256>,
chain_id: Vec<u64>,
}

#[async_trait::async_trait]
impl Dataset for Erc20Approvals {
fn default_columns() -> Option<Vec<&'static str>> {
Some(vec![
"block_number",
// "block_hash",
"transaction_index",
"log_index",
"transaction_hash",
"erc20",
"from_address",
"to_address",
"value",
"chain_id",
])
}

fn optional_parameters() -> Vec<Dim> {
vec![Dim::Address, Dim::Topic0, Dim::Topic1, Dim::Topic2, Dim::FromAddress, Dim::ToAddress]
}

fn use_block_ranges() -> bool {
true
}

fn arg_aliases() -> Option<std::collections::HashMap<Dim, Dim>> {
Some([(Dim::Contract, Dim::Address)].into_iter().collect())
}
}

#[async_trait::async_trait]
impl CollectByBlock for Erc20Approvals {
type Response = Vec<Log>;

async fn extract(request: Params, source: Arc<Source>, _: Arc<Query>) -> R<Self::Response> {
let mut topics = [Some(ValueOrArray::Value(Some(*EVENT_ERC20_TRANSFER))), None, None, None];
if let Some(from_address) = &request.from_address {
let mut v = vec![0u8; 12];
v.append(&mut from_address.to_owned());
topics[1] = Some(ValueOrArray::Value(Some(H256::from_slice(&v[..]))));
}
if let Some(to_address) = &request.to_address {
let mut v = vec![0u8; 12];
v.append(&mut to_address.to_owned());
topics[2] = Some(ValueOrArray::Value(Some(H256::from_slice(&v[..]))));
}
let filter = Filter { topics, ..request.ethers_log_filter()? };
let logs = source.get_logs(&filter).await?;

Ok(logs.into_iter().filter(|x| x.topics.len() == 3 && x.data.len() == 32).collect())
}

fn transform(response: Self::Response, columns: &mut Self, query: &Arc<Query>) -> R<()> {
let schema = query.schemas.get_schema(&Datatype::Erc20Approvals)?;
process_erc20_approval(response, columns, schema)
}
}

#[async_trait::async_trait]
impl CollectByTransaction for Erc20Approvals {
type Response = Vec<Log>;

async fn extract(request: Params, source: Arc<Source>, _: Arc<Query>) -> R<Self::Response> {
let logs = source.get_transaction_logs(request.transaction_hash()?).await?;
Ok(logs.into_iter().filter(is_erc20_approval).collect())
}
}

fn is_erc20_approval(log: &Log) -> bool {
log.topics.len() == 3 && log.data.len() == 32 && log.topics[0] == *EVENT_ERC20_APPROVAL
}

fn process_erc20_approval(logs: Vec<Log>, columns: &mut Erc20Approvals, schema: &Table) -> R<()> {
for log in logs.iter() {
if let (Some(bn), Some(tx), Some(ti), Some(li)) =
(log.block_number, log.transaction_hash, log.transaction_index, log.log_index)
{
columns.n_rows += 1;
store!(schema, columns, block_number, bn.as_u32());
store!(schema, columns, block_hash, log.block_hash.map(|bh| bh.as_bytes().to_vec()));
store!(schema, columns, transaction_index, ti.as_u32());
store!(schema, columns, log_index, li.as_u32());
store!(schema, columns, transaction_hash, tx.as_bytes().to_vec());
store!(schema, columns, erc20, log.address.as_bytes().to_vec());
store!(schema, columns, from_address, log.topics[1].as_bytes()[12..].to_vec());
store!(schema, columns, to_address, log.topics[2].as_bytes()[12..].to_vec());
store!(schema, columns, value, log.data.to_vec().as_slice().into());
}
}
Ok(())
}
3 changes: 3 additions & 0 deletions crates/freeze/src/datasets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub mod code_reads;
pub mod codes;
/// contracts
pub mod contracts;
/// erc20 approval
pub mod erc20_approvals;
/// erc20 balances
pub mod erc20_balances;
/// erc20 metadata
Expand Down Expand Up @@ -80,6 +82,7 @@ pub use code_diffs::*;
pub use code_reads::*;
pub use codes::*;
pub use contracts::*;
pub use erc20_approvals::*;
pub use erc20_balances::*;
pub use erc20_metadata::*;
pub use erc20_supplies::*;
Expand Down
1 change: 1 addition & 0 deletions crates/freeze/src/types/datatypes/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ define_datatypes!(
Erc20Metadata,
Erc20Supplies,
Erc20Transfers,
Erc20Approvals,
Erc721Metadata,
Erc721Transfers,
EthCalls,
Expand Down
6 changes: 6 additions & 0 deletions crates/freeze/src/types/signatures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ lazy_static::lazy_static! {
.expect("Decoding failed"),
);

/// event hash of EVENT_ERC20_APPROVAL
pub static ref EVENT_ERC20_APPROVAL: H256 = H256(
prefix_hex::decode("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925")
.expect("Decoding failed"),
);

/// event hash of EVENT_ERC721_TRANSFER
pub static ref EVENT_ERC721_TRANSFER: H256 = H256(
prefix_hex::decode("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
Expand Down

0 comments on commit 24fc2f7

Please sign in to comment.