1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use crate::pb;
use hex;
use std::str;
use num_bigint::BigUint;
const TRANSFER_TOPIC: &str = "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
pub fn is_erc20transfer_event(log: &pb::eth::Log) -> bool {
if log.topics.len() != 3 || log.data.len() != 32 {
return false;
}
return hex::encode(&log.topics[0]) == TRANSFER_TOPIC;
}
pub fn find_erc20_storage_changes(call: &pb::eth::Call, holder: &Vec<u8>) -> Vec<pb::erc20::BalanceChange> {
let mut out: Vec<pb::erc20::BalanceChange> = Vec::new();
let keys = erc20storage_keys_from_address(call, holder);
for key in keys {
let byte_key = hex::decode(key).unwrap();
for change in &call.storage_changes {
if change.key.eq(&byte_key) {
let new_balance = BigUint::from_bytes_le(change.new_value.as_slice()).to_string();
let old_balance = BigUint::from_bytes_le(change.old_value.as_slice()).to_string();
let erc20_balance_change = &pb::erc20::BalanceChange {
old_balance,
new_balance
};
out.push(erc20_balance_change.clone())
}
}
}
return out;
}
fn erc20storage_keys_from_address(call: &pb::eth::Call, addr: &Vec<u8>) -> Vec<String> {
let mut out: Vec<String> = Vec::new();
let addr_as_hex = hex::encode(addr);
for (hash, pre_image) in &call.keccak_preimages {
if pre_image.chars().count() != 128 {
continue;
}
if &pre_image[64..126] != "00000000000000000000000000000000000000000000000000000000000000" {
continue;
}
if &pre_image[24..64] == addr_as_hex {
out.push(String::from(hash));
}
}
return out;
}