Sdk implementation: Sfrax adapter and substream (#91)

* feat: initial setup

* feat: implemented getCapabilities and getTokens

* chore: adjusted getPoolIds

* feat: Initial implementation of getLimits()

* feat: implemented getLimits, getTokens and internal functions for amounts

* feat: implemented price

* feat: implemented swap function

* fix and test: fixed minor issues on adapter and setup test

* debugging price function

* fix: debugged price function and fixed getPriceAt function

* test: testOneIncreasingPriceFoundFraxV3SFrax

* fix: debugging and fixing buy function

* fix: fixed getPriceAt

* test: testing post trade price

* fix: Fixed getPriceAt

* fix: Fixed getLimits

* fix: Fixed prices and improved readability

* fix: Fixed price and transfers in swap

* feat: Finished tests

* chore: Changed approve to safeIncreaseAllowance

* feat: created substream for staked frax

* feat: remove useless files

* feat: fixed dependencies in cargo.toml

* feat: rename folder

* feat: updated cargo.lock

* feat: changed lib.rs, added modules.rs

* feat: update modules.rs with corrects addresses

* feat: rename folder in ethereum-sfrax

* feat: remove useless comments, change locked asset address, rename

* feat: undo changes on mod.rs in ethereum-balancer

* feat: rename variable

* feat: update substreams/cargo.toml

* feat: modify ristfmt.toml

* feat: performed code formatting

* feat: modify src/abi

* feat: performed formatting with nightly

* feat: fix addition opeation

* feat: adjust code with for i, f

* feat: performed fmt inside ethereum-sfrax folder

* feat: performed clippy

* feat: fix with clippy warning suggests

* feat: undo any change in ethereum-balancer

* feat: change stakedfrax_contract.rs

* fix: stakedfrax_contract.rs

* feat: add blank line

* feat: add #[allow(clippy::all)] on ethereum-sfrax/src/abi/mod.rs

* feat: update comments on pool_factories.rs

* feat: update cargo.toml and substreams.yaml

* feat: add tycho evm in pb folder

* feat: add params to take contracts' addresses

* feat: add logic to map rewards_cycle

* feat: performed fmt and fix versioning

* feat: remove useless functions

* feat: add logic to track rewards_to_distribute

* feat: passing CI

* fix: substreams.yaml

* feat: fixed params in manifest

Co-authored-by: mrBovo <bovo.ignazio@proton.me>

* feat: fixed error in map_relative_balances function

* feat: passing CI checks

* fix: 🐛 hex-binary address encoding + refactoring vault-> underlying map

* style: 💄 fix formatting

* feat: Implemented testPoolBehaviour

* alignment with propeller main

* Update forge-std submodule reference to include ds-test

* files update to match propeller/main

* creating integration_test fir sfrax

* fixed FraxV3SFraxAdapter.sol import paths

* updated with correct addresses FraxV3SFraxAdapter manifest.yaml

* updated sfrax manifest.yaml

* updated to support sdk

* integration_test sfrax updated

* fix: 🐛 add reward processing

* chore: ♻️ minor cleanups

* fix: Fixed adapter limits

* fix: fix adapter and substream sdk tests

* fix: Fixed CI errors

* chore: fmt

* chore: Removed unused line

* fix: Fixed clippy warnings

* chore: formatted with rustup

* chore: Removed unused line

* chore: post-build formatting

* chore: Formatting using different toolchain vesion

* chore: 💄 format

* chore: 💄 format 2

* chore: Using static address for frax

* feat: Added second constructor param for sfrax

* fix: Fixed limits on frax sell

* chore: Fixed merge conflict with sfraxeth

* chore: Remove sfraxeth_contract changes

* chore: Fixed EOFs

* fix: Fixed fmt on stakedfrax contract

---------

Co-authored-by: mp-web3 <mp.web3.t@gmail.com>
Co-authored-by: gabrir99 <gabri.ruini@gmail.com>
Co-authored-by: mrBovo <bovo.ignazio@proton.me>
Co-authored-by: Ignazio Bovo <ignazio@jsgenesis.com>
Co-authored-by: mrBovo <bovoignazio.dev@gmail.com>
Co-authored-by: Mattia <mp.web3@gmail.com>
This commit is contained in:
Domenico
2024-10-25 19:53:06 +02:00
committed by GitHub
parent 549ca39d1a
commit e484ea28ca
23 changed files with 8821 additions and 31 deletions

1108
substreams/ethereum-sfrax/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
[package]
name = "ethereum-sfrax"
version = "0.1.0"
edition = "2021"
[lib]
name = "ethereum_sfrax"
crate-type = ["cdylib"]
[dependencies]
ethabi = "17"
hex-literal.workspace = true
num-bigint = "0.4"
num-traits = "0.2.15"
prost.workspace = true
prost-types = "0.11"
substreams.workspace = true
substreams-ethereum.workspace = true
hex.workspace = true
tycho-substreams.workspace = true
itertools = "0.12.0"
anyhow = "1.0.75"
[build-dependencies]
anyhow = "1"
substreams-ethereum = "0.9"
regex = "1.10.4"
# Required so that ethabi > ethereum-types build correctly under wasm32-unknown-unknown
[target.wasm32-unknown-unknown.dependencies]
getrandom = { version = "0.2", features = ["custom"] }

View File

@@ -0,0 +1,26 @@
CARGO_VERSION := $(shell cargo version 2>/dev/null)
.PHONY: build
build:
ifdef CARGO_VERSION
cargo build --target wasm32-unknown-unknown --release
else
@echo "Building substreams target using Docker. To speed up this step, install a Rust development environment."
docker run --rm -ti --init -v ${PWD}:/usr/src --workdir /usr/src/ rust:bullseye cargo build --target wasm32-unknown-unknown --release
endif
.PHONY: run
run: build
substreams run substreams.yaml $(if $(MODULE),$(MODULE),map_events) $(if $(START_BLOCK),-s $(START_BLOCK)) $(if $(STOP_BLOCK),-t $(STOP_BLOCK))
.PHONY: gui
gui: build
substreams gui substreams.yaml $(if $(MODULE),$(MODULE),map_events) $(if $(START_BLOCK),-s $(START_BLOCK)) $(if $(STOP_BLOCK),-t $(STOP_BLOCK))
.PHONY: protogen
protogen:
substreams protogen ./substreams.yaml --exclude-paths="sf/substreams,google"
.PHONY: pack
pack: build
substreams pack substreams.yaml

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
version: v1
plugins:
- plugin: buf.build/community/neoeinstein-prost:v0.2.2
out: src/pb
opt:
- file_descriptor_set=false
- plugin: buf.build/community/neoeinstein-prost-crate:v0.3.1
out: src/pb
opt:
- no_features

View File

@@ -0,0 +1,24 @@
#![allow(clippy::all)]
use anyhow::{Ok, Result};
use regex::Regex;
use std::fs;
use substreams_ethereum::Abigen;
fn main() -> Result<(), anyhow::Error> {
let file_names = ["abi/stakedfrax_contract.abi.json"];
let file_output_names = ["src/abi/stakedfrax_contract.rs"];
for (i, f) in file_names.into_iter().enumerate() {
let contents = fs::read_to_string(f).expect("Should have been able to read the file");
// sanitize fields and attributes starting with an underscore
let regex = Regex::new(r#"("\w+"\s?:\s?")_(\w+")"#).unwrap();
let sanitized_abi_file = regex.replace_all(contents.as_str(), "${1}u_${2}");
Abigen::from_bytes("Contract", sanitized_abi_file.as_bytes())?
.generate()?
.write_to_file(file_output_names[i])?;
}
Ok(())
}

View File

@@ -0,0 +1,31 @@
# Name of the substreams config file in your substreams module. Usually "./substreams.yaml"
substreams_yaml_path: ./substreams.yaml
# Name of the adapter contract, usually: ProtocolSwapAdapter
adapter_contract: "FraxV3SFraxAdapter"
# Constructor signature of the Adapter contract
adapter_build_signature: "constructor(address)"
# A comma separated list of args to be passed to the constructor of the Adapter contract
adapter_build_args: "0xA663B02CF0a4b149d2aD41910CB81e23e1c41c32,0x853d955aCEf822Db058eb8505911ED77F175b99e"
# Whether or not the testing script should skip checking balances of the protocol components.
# If set to `true` please always add a reason why it's skipped.
skip_balance_check: true
# A list of protocol types names created by your Substreams module.
protocol_type_names:
- "sfrax_vault"
# A list of tests.
tests:
# Test to validate the creation of the sFrax vault
- name: test_sfrax_vault_creation
# Indexed block range where the vault was created
start_block: 18378085
stop_block: 18380714 #2629 blocks difference 18380714
# Same as global `initialized_accounts` but only scoped to this test.
expected_components:
- id: "0xA663B02CF0a4b149d2aD41910CB81e23e1c41c32" # sFrax Vault
tokens:
- "0x853d955aCEf822Db058eb8505911ED77F175b99e" # FRAX
- "0xA663B02CF0a4b149d2aD41910CB81e23e1c41c32" # sFrax
creation_tx: "0xecd4ab27bc3b4c300b11405fc6a156ee316ad3f4c24f63130cbcbc49ae6bef55"
skip_simulation: false

View File

@@ -0,0 +1,276 @@
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package contract.v1;
message Events {
repeated stakedfrax_Approval stakedfrax_approvals = 1;
repeated stakedfrax_Deposit stakedfrax_deposits = 2;
repeated stakedfrax_DistributeRewards stakedfrax_distribute_rewards = 3;
repeated stakedfrax_SetMaxDistributionPerSecondPerAsset stakedfrax_set_max_distribution_per_second_per_assets = 4;
repeated stakedfrax_SyncRewards stakedfrax_sync_rewards = 5;
repeated stakedfrax_TimelockTransferStarted stakedfrax_timelock_transfer_starteds = 6;
repeated stakedfrax_TimelockTransferred stakedfrax_timelock_transferreds = 7;
repeated stakedfrax_Transfer stakedfrax_transfers = 8;
repeated stakedfrax_Withdraw stakedfrax_withdraws = 9;
}
message Calls {
repeated stakedfrax_AcceptTransferTimelockCall stakedfrax_call_accept_transfer_timelocks = 1;
repeated stakedfrax_ApproveCall stakedfrax_call_approves = 2;
repeated stakedfrax_DepositCall stakedfrax_call_deposits = 3;
repeated stakedfrax_DepositWithSignatureCall stakedfrax_call_deposit_with_signatures = 4;
repeated stakedfrax_MintCall stakedfrax_call_mints = 5;
repeated stakedfrax_PermitCall stakedfrax_call_permits = 6;
repeated stakedfrax_RedeemCall stakedfrax_call_redeems = 7;
repeated stakedfrax_RenounceTimelockCall stakedfrax_call_renounce_timelocks = 8;
repeated stakedfrax_SetMaxDistributionPerSecondPerAssetCall stakedfrax_call_set_max_distribution_per_second_per_assets = 9;
repeated stakedfrax_SyncRewardsAndDistributionCall stakedfrax_call_sync_rewards_and_distributions = 10;
repeated stakedfrax_TransferCall stakedfrax_call_transfers = 11;
repeated stakedfrax_TransferFromCall stakedfrax_call_transfer_froms = 12;
repeated stakedfrax_TransferTimelockCall stakedfrax_call_transfer_timelocks = 13;
repeated stakedfrax_WithdrawCall stakedfrax_call_withdraws = 14;
}
message stakedfrax_Approval {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
bytes owner = 5;
bytes spender = 6;
string amount = 7;
}
message stakedfrax_Deposit {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
bytes caller = 5;
bytes owner = 6;
string assets = 7;
string shares = 8;
}
message stakedfrax_DistributeRewards {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
string rewards_to_distribute = 5;
}
message stakedfrax_SetMaxDistributionPerSecondPerAsset {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
string old_max = 5;
string new_max = 6;
}
message stakedfrax_SyncRewards {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
uint64 cycle_end = 5;
uint64 last_sync = 6;
string reward_cycle_amount = 7;
}
message stakedfrax_TimelockTransferStarted {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
bytes previous_timelock = 5;
bytes new_timelock = 6;
}
message stakedfrax_TimelockTransferred {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
bytes previous_timelock = 5;
bytes new_timelock = 6;
}
message stakedfrax_Transfer {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
bytes from = 5;
bytes to = 6;
string amount = 7;
}
message stakedfrax_Withdraw {
string evt_tx_hash = 1;
uint32 evt_index = 2;
google.protobuf.Timestamp evt_block_time = 3;
uint64 evt_block_number = 4;
bytes caller = 5;
bytes receiver = 6;
bytes owner = 7;
string assets = 8;
string shares = 9;
}
message stakedfrax_AcceptTransferTimelockCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
}
message stakedfrax_ApproveCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
bytes spender = 6;
string amount = 7;
bool output_param0 = 8;
}
message stakedfrax_DepositCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
string u_assets = 6;
bytes u_receiver = 7;
string output__shares = 8;
}
message stakedfrax_DepositWithSignatureCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
string u_assets = 6;
bytes u_receiver = 7;
string u_deadline = 8;
bool u_approve_max = 9;
uint64 u_v = 10;
bytes u_r = 11;
bytes u_s = 12;
string output__shares = 13;
}
message stakedfrax_MintCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
string u_shares = 6;
bytes u_receiver = 7;
string output__assets = 8;
}
message stakedfrax_PermitCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
bytes owner = 6;
bytes spender = 7;
string value = 8;
string deadline = 9;
uint64 v = 10;
bytes r = 11;
bytes s = 12;
}
message stakedfrax_RedeemCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
string u_shares = 6;
bytes u_receiver = 7;
bytes u_owner = 8;
string output__assets = 9;
}
message stakedfrax_RenounceTimelockCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
}
message stakedfrax_SetMaxDistributionPerSecondPerAssetCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
string u_max_distribution_per_second_per_asset = 6;
}
message stakedfrax_SyncRewardsAndDistributionCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
}
message stakedfrax_TransferCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
bytes to = 6;
string amount = 7;
bool output_param0 = 8;
}
message stakedfrax_TransferFromCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
bytes from = 6;
bytes to = 7;
string amount = 8;
bool output_param0 = 9;
}
message stakedfrax_TransferTimelockCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
bytes u_new_timelock = 6;
}
message stakedfrax_WithdrawCall {
string call_tx_hash = 1;
google.protobuf.Timestamp call_block_time = 2;
uint64 call_block_number = 3;
uint64 call_ordinal = 4;
bool call_success = 5;
string u_assets = 6;
bytes u_receiver = 7;
bytes u_owner = 8;
string output__shares = 9;
}

View File

@@ -0,0 +1,4 @@
[toolchain]
channel = "1.75"
components = ["rustfmt"]
targets = ["wasm32-unknown-unknown"]

View File

@@ -0,0 +1,2 @@
#[allow(clippy::all)]
pub mod stakedfrax_contract;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
mod abi;
mod modules;
pub mod pb;

View File

@@ -0,0 +1,277 @@
use crate::abi;
use anyhow::Result;
use itertools::Itertools;
use std::collections::HashMap;
use substreams::{
hex,
pb::substreams::StoreDeltas,
store::{StoreAdd, StoreAddBigInt, StoreAddInt64, StoreGet, StoreGetInt64, StoreNew},
};
use substreams_ethereum::{
pb::eth::{self},
Event,
};
use tycho_substreams::{
balances::aggregate_balances_changes, contract::extract_contract_changes, prelude::*,
};
#[substreams::handlers::map]
pub fn map_components(
params: String,
block: eth::v2::Block,
) -> Result<BlockTransactionProtocolComponents, anyhow::Error> {
let vault_address = hex::decode(params).unwrap();
let locked_asset = find_deployed_underlying_address(&vault_address).unwrap();
// We store these as a hashmap by tx hash since we need to agg by tx hash later
Ok(BlockTransactionProtocolComponents {
tx_components: block
.transactions()
.filter_map(|tx| {
let components = tx
.calls()
.filter(|call| !call.call.state_reverted)
.filter_map(|_| {
// address doesn't exist before contract deployment, hence the first tx with
// a log.address = vault_address is the deployment tx
if is_deployment_tx(tx, &vault_address) {
Some(
ProtocolComponent::at_contract(&vault_address, &tx.into())
.with_tokens(&[
locked_asset.as_slice(),
vault_address.as_slice(),
])
.as_swap_type("sfrax_vault", ImplementationType::Vm),
)
} else {
None
}
})
.collect::<Vec<_>>();
if !components.is_empty() {
Some(TransactionProtocolComponents { tx: Some(tx.into()), components })
} else {
None
}
})
.collect::<Vec<_>>(),
})
}
#[substreams::handlers::store]
pub fn store_components(map: BlockTransactionProtocolComponents, store: StoreAddInt64) {
store.add_many(
0,
&map.tx_components
.iter()
.flat_map(|tx_components| &tx_components.components)
.map(|component| format!("pool:{0}", component.id))
.collect::<Vec<_>>(),
1,
);
}
#[substreams::handlers::map]
pub fn map_relative_balances(
block: eth::v2::Block,
store: StoreGetInt64,
) -> Result<BlockBalanceDeltas, anyhow::Error> {
let balance_deltas = block
.logs()
.flat_map(|vault_log| {
let mut deltas = Vec::new();
if let Some(ev) =
abi::stakedfrax_contract::events::Withdraw::match_and_decode(vault_log.log)
{
let address_bytes_be = vault_log.address();
let address_hex = format!("0x{}", hex::encode(address_bytes_be));
if store
.get_last(format!("pool:{}", address_hex))
.is_some()
{
deltas.extend_from_slice(&[
BalanceDelta {
ord: vault_log.ordinal(),
tx: Some(vault_log.receipt.transaction.into()),
token: find_deployed_underlying_address(address_bytes_be)
.unwrap()
.to_vec(),
delta: ev.assets.neg().to_signed_bytes_be(),
component_id: address_hex.as_bytes().to_vec(),
},
BalanceDelta {
ord: vault_log.ordinal(),
tx: Some(vault_log.receipt.transaction.into()),
token: address_bytes_be.to_vec(),
delta: ev.shares.neg().to_signed_bytes_be(),
component_id: address_hex.as_bytes().to_vec(),
},
]);
substreams::log::debug!(
"Withdraw: vault: {}, frax:- {}, sfrax:- {}",
address_hex,
ev.assets,
ev.shares
);
}
} else if let Some(ev) =
abi::stakedfrax_contract::events::Deposit::match_and_decode(vault_log.log)
{
let address_bytes_be = vault_log.address();
let address_hex = format!("0x{}", hex::encode(address_bytes_be));
if store
.get_last(format!("pool:{}", address_hex))
.is_some()
{
deltas.extend_from_slice(&[
BalanceDelta {
ord: vault_log.ordinal(),
tx: Some(vault_log.receipt.transaction.into()),
token: find_deployed_underlying_address(address_bytes_be)
.unwrap()
.to_vec(),
delta: ev.assets.to_signed_bytes_be(),
component_id: address_hex.as_bytes().to_vec(),
},
BalanceDelta {
ord: vault_log.ordinal(),
tx: Some(vault_log.receipt.transaction.into()),
token: address_bytes_be.to_vec(),
delta: ev.shares.to_signed_bytes_be(),
component_id: address_hex.as_bytes().to_vec(),
},
]);
substreams::log::debug!(
"Deposit: vault: {}, frax:+ {}, sfrax:+ {}",
address_hex,
ev.assets,
ev.shares
);
}
} else if let Some(ev) =
abi::stakedfrax_contract::events::DistributeRewards::match_and_decode(vault_log.log)
{
let address_bytes_be = vault_log.address();
let address_hex = format!("0x{}", hex::encode(address_bytes_be));
if store
.get_last(format!("pool:{}", address_hex))
.is_some()
{
deltas.extend_from_slice(&[BalanceDelta {
ord: vault_log.ordinal(),
tx: Some(vault_log.receipt.transaction.into()),
token: address_bytes_be.to_vec(),
delta: ev
.rewards_to_distribute
.to_signed_bytes_be(),
component_id: address_hex.as_bytes().to_vec(),
}]);
// Log token and amount without encoding
substreams::log::debug!(
"DistributeRewards: vault: {}, frax:+ {}",
address_hex,
ev.rewards_to_distribute
);
}
}
deltas
})
.collect::<Vec<_>>();
Ok(BlockBalanceDeltas { balance_deltas })
}
#[substreams::handlers::store]
pub fn store_balances(deltas: BlockBalanceDeltas, store: StoreAddBigInt) {
tycho_substreams::balances::store_balance_changes(deltas, store);
}
#[substreams::handlers::map]
pub fn map_protocol_changes(
block: eth::v2::Block,
grouped_components: BlockTransactionProtocolComponents,
deltas: BlockBalanceDeltas,
components_store: StoreGetInt64,
balance_store: StoreDeltas,
) -> Result<BlockChanges, anyhow::Error> {
let mut transaction_contract: HashMap<u64, TransactionChanges> = HashMap::new();
grouped_components
.tx_components
.iter()
.for_each(|tx_component| {
let tx = tx_component.tx.as_ref().unwrap();
transaction_contract
.entry(tx.index)
.or_insert_with(|| TransactionChanges::new(tx))
.component_changes
.extend_from_slice(&tx_component.components);
});
aggregate_balances_changes(balance_store, deltas)
.into_iter()
.for_each(|(_, (tx, balances))| {
transaction_contract
.entry(tx.index)
.or_insert_with(|| TransactionChanges::new(&tx))
.balance_changes
.extend(balances.into_values());
});
extract_contract_changes(
&block,
|addr| {
components_store
.get_last(format!("pool:0x{0}", hex::encode(addr)))
.is_some()
},
&mut transaction_contract,
);
Ok(BlockChanges {
block: Some((&block).into()),
changes: transaction_contract
.drain()
.sorted_unstable_by_key(|(index, _)| *index)
.filter_map(|(_, change)| {
if change.contract_changes.is_empty() &&
change.component_changes.is_empty() &&
change.balance_changes.is_empty()
{
None
} else {
Some(change)
}
})
.collect::<Vec<_>>(),
})
}
fn is_deployment_tx(tx: &eth::v2::TransactionTrace, vault_address: &[u8]) -> bool {
let created_accounts = tx
.calls
.iter()
.flat_map(|call| {
call.account_creations
.iter()
.map(|ac| ac.account.to_owned())
})
.collect::<Vec<_>>();
if let Some(deployed_address) = created_accounts.first() {
return deployed_address.as_slice() == vault_address;
}
false
}
fn find_deployed_underlying_address(vault_address: &[u8]) -> Option<[u8; 20]> {
match vault_address {
hex!("A663B02CF0a4b149d2aD41910CB81e23e1c41c32") => {
Some(hex!("853d955aCEf822Db058eb8505911ED77F175b99e"))
}
_ => None,
}
}

View File

@@ -0,0 +1,508 @@
// @generated
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Events {
#[prost(message, repeated, tag="1")]
pub stakedfrax_approvals: ::prost::alloc::vec::Vec<StakedfraxApproval>,
#[prost(message, repeated, tag="2")]
pub stakedfrax_deposits: ::prost::alloc::vec::Vec<StakedfraxDeposit>,
#[prost(message, repeated, tag="3")]
pub stakedfrax_distribute_rewards: ::prost::alloc::vec::Vec<StakedfraxDistributeRewards>,
#[prost(message, repeated, tag="4")]
pub stakedfrax_set_max_distribution_per_second_per_assets: ::prost::alloc::vec::Vec<StakedfraxSetMaxDistributionPerSecondPerAsset>,
#[prost(message, repeated, tag="5")]
pub stakedfrax_sync_rewards: ::prost::alloc::vec::Vec<StakedfraxSyncRewards>,
#[prost(message, repeated, tag="6")]
pub stakedfrax_timelock_transfer_starteds: ::prost::alloc::vec::Vec<StakedfraxTimelockTransferStarted>,
#[prost(message, repeated, tag="7")]
pub stakedfrax_timelock_transferreds: ::prost::alloc::vec::Vec<StakedfraxTimelockTransferred>,
#[prost(message, repeated, tag="8")]
pub stakedfrax_transfers: ::prost::alloc::vec::Vec<StakedfraxTransfer>,
#[prost(message, repeated, tag="9")]
pub stakedfrax_withdraws: ::prost::alloc::vec::Vec<StakedfraxWithdraw>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Calls {
#[prost(message, repeated, tag="1")]
pub stakedfrax_call_accept_transfer_timelocks: ::prost::alloc::vec::Vec<StakedfraxAcceptTransferTimelockCall>,
#[prost(message, repeated, tag="2")]
pub stakedfrax_call_approves: ::prost::alloc::vec::Vec<StakedfraxApproveCall>,
#[prost(message, repeated, tag="3")]
pub stakedfrax_call_deposits: ::prost::alloc::vec::Vec<StakedfraxDepositCall>,
#[prost(message, repeated, tag="4")]
pub stakedfrax_call_deposit_with_signatures: ::prost::alloc::vec::Vec<StakedfraxDepositWithSignatureCall>,
#[prost(message, repeated, tag="5")]
pub stakedfrax_call_mints: ::prost::alloc::vec::Vec<StakedfraxMintCall>,
#[prost(message, repeated, tag="6")]
pub stakedfrax_call_permits: ::prost::alloc::vec::Vec<StakedfraxPermitCall>,
#[prost(message, repeated, tag="7")]
pub stakedfrax_call_redeems: ::prost::alloc::vec::Vec<StakedfraxRedeemCall>,
#[prost(message, repeated, tag="8")]
pub stakedfrax_call_renounce_timelocks: ::prost::alloc::vec::Vec<StakedfraxRenounceTimelockCall>,
#[prost(message, repeated, tag="9")]
pub stakedfrax_call_set_max_distribution_per_second_per_assets: ::prost::alloc::vec::Vec<StakedfraxSetMaxDistributionPerSecondPerAssetCall>,
#[prost(message, repeated, tag="10")]
pub stakedfrax_call_sync_rewards_and_distributions: ::prost::alloc::vec::Vec<StakedfraxSyncRewardsAndDistributionCall>,
#[prost(message, repeated, tag="11")]
pub stakedfrax_call_transfers: ::prost::alloc::vec::Vec<StakedfraxTransferCall>,
#[prost(message, repeated, tag="12")]
pub stakedfrax_call_transfer_froms: ::prost::alloc::vec::Vec<StakedfraxTransferFromCall>,
#[prost(message, repeated, tag="13")]
pub stakedfrax_call_transfer_timelocks: ::prost::alloc::vec::Vec<StakedfraxTransferTimelockCall>,
#[prost(message, repeated, tag="14")]
pub stakedfrax_call_withdraws: ::prost::alloc::vec::Vec<StakedfraxWithdrawCall>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxApproval {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(bytes="vec", tag="5")]
pub owner: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="6")]
pub spender: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="7")]
pub amount: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxDeposit {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(bytes="vec", tag="5")]
pub caller: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="6")]
pub owner: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="7")]
pub assets: ::prost::alloc::string::String,
#[prost(string, tag="8")]
pub shares: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxDistributeRewards {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(string, tag="5")]
pub rewards_to_distribute: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxSetMaxDistributionPerSecondPerAsset {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(string, tag="5")]
pub old_max: ::prost::alloc::string::String,
#[prost(string, tag="6")]
pub new_max: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxSyncRewards {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(uint64, tag="5")]
pub cycle_end: u64,
#[prost(uint64, tag="6")]
pub last_sync: u64,
#[prost(string, tag="7")]
pub reward_cycle_amount: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxTimelockTransferStarted {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(bytes="vec", tag="5")]
pub previous_timelock: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="6")]
pub new_timelock: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxTimelockTransferred {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(bytes="vec", tag="5")]
pub previous_timelock: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="6")]
pub new_timelock: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxTransfer {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(bytes="vec", tag="5")]
pub from: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="6")]
pub to: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="7")]
pub amount: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxWithdraw {
#[prost(string, tag="1")]
pub evt_tx_hash: ::prost::alloc::string::String,
#[prost(uint32, tag="2")]
pub evt_index: u32,
#[prost(message, optional, tag="3")]
pub evt_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="4")]
pub evt_block_number: u64,
#[prost(bytes="vec", tag="5")]
pub caller: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="6")]
pub receiver: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="7")]
pub owner: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="8")]
pub assets: ::prost::alloc::string::String,
#[prost(string, tag="9")]
pub shares: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxAcceptTransferTimelockCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxApproveCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(bytes="vec", tag="6")]
pub spender: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="7")]
pub amount: ::prost::alloc::string::String,
#[prost(bool, tag="8")]
pub output_param0: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxDepositCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(string, tag="6")]
pub u_assets: ::prost::alloc::string::String,
#[prost(bytes="vec", tag="7")]
pub u_receiver: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="8")]
pub output_shares: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxDepositWithSignatureCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(string, tag="6")]
pub u_assets: ::prost::alloc::string::String,
#[prost(bytes="vec", tag="7")]
pub u_receiver: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="8")]
pub u_deadline: ::prost::alloc::string::String,
#[prost(bool, tag="9")]
pub u_approve_max: bool,
#[prost(uint64, tag="10")]
pub u_v: u64,
#[prost(bytes="vec", tag="11")]
pub u_r: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="12")]
pub u_s: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="13")]
pub output_shares: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxMintCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(string, tag="6")]
pub u_shares: ::prost::alloc::string::String,
#[prost(bytes="vec", tag="7")]
pub u_receiver: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="8")]
pub output_assets: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxPermitCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(bytes="vec", tag="6")]
pub owner: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="7")]
pub spender: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="8")]
pub value: ::prost::alloc::string::String,
#[prost(string, tag="9")]
pub deadline: ::prost::alloc::string::String,
#[prost(uint64, tag="10")]
pub v: u64,
#[prost(bytes="vec", tag="11")]
pub r: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="12")]
pub s: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxRedeemCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(string, tag="6")]
pub u_shares: ::prost::alloc::string::String,
#[prost(bytes="vec", tag="7")]
pub u_receiver: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="8")]
pub u_owner: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="9")]
pub output_assets: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxRenounceTimelockCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxSetMaxDistributionPerSecondPerAssetCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(string, tag="6")]
pub u_max_distribution_per_second_per_asset: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxSyncRewardsAndDistributionCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxTransferCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(bytes="vec", tag="6")]
pub to: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="7")]
pub amount: ::prost::alloc::string::String,
#[prost(bool, tag="8")]
pub output_param0: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxTransferFromCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(bytes="vec", tag="6")]
pub from: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="7")]
pub to: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="8")]
pub amount: ::prost::alloc::string::String,
#[prost(bool, tag="9")]
pub output_param0: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxTransferTimelockCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(bytes="vec", tag="6")]
pub u_new_timelock: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StakedfraxWithdrawCall {
#[prost(string, tag="1")]
pub call_tx_hash: ::prost::alloc::string::String,
#[prost(message, optional, tag="2")]
pub call_block_time: ::core::option::Option<::prost_types::Timestamp>,
#[prost(uint64, tag="3")]
pub call_block_number: u64,
#[prost(uint64, tag="4")]
pub call_ordinal: u64,
#[prost(bool, tag="5")]
pub call_success: bool,
#[prost(string, tag="6")]
pub u_assets: ::prost::alloc::string::String,
#[prost(bytes="vec", tag="7")]
pub u_receiver: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes="vec", tag="8")]
pub u_owner: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="9")]
pub output_shares: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RewardCycle {
#[prost(uint64, tag="1")]
pub ord: u64,
#[prost(bytes="vec", tag="2")]
pub reward_rate: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag="3")]
pub component_id: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockRewardCycles {
#[prost(message, repeated, tag="1")]
pub reward_cycles: ::prost::alloc::vec::Vec<RewardCycle>,
}
// @@protoc_insertion_point(module)

View File

@@ -0,0 +1,18 @@
#[allow(clippy::all)]
// @generated
pub mod contract {
// @@protoc_insertion_point(attribute:contract.v1)
pub mod v1 {
include!("contract.v1.rs");
// @@protoc_insertion_point(contract.v1)
}
}
pub mod tycho {
pub mod evm {
// @@protoc_insertion_point(attribute:tycho.evm.v1)
pub mod v1 {
include!("tycho.evm.v1.rs");
// @@protoc_insertion_point(tycho.evm.v1)
}
}
}

View File

@@ -0,0 +1,373 @@
// @generated
// WARNING: DEPRECATED. Please use common.proto's TransactionChanges and BlockChanges instead.
// This file contains proto definitions specific to the VM integration.
/// A set of changes aggregated by transaction.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionContractChanges {
/// The transaction instance that results in the changes.
#[prost(message, optional, tag = "1")]
pub tx: ::core::option::Option<Transaction>,
/// Contains the changes induced by the above transaction, aggregated on a per-contract basis.
#[prost(message, repeated, tag = "2")]
pub contract_changes: ::prost::alloc::vec::Vec<ContractChange>,
/// An array of newly added components.
#[prost(message, repeated, tag = "3")]
pub component_changes: ::prost::alloc::vec::Vec<ProtocolComponent>,
/// An array of balance changes to components.
#[prost(message, repeated, tag = "4")]
pub balance_changes: ::prost::alloc::vec::Vec<BalanceChange>,
}
/// A set of transaction changes within a single block.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockContractChanges {
/// The block for which these changes are collectively computed.
#[prost(message, optional, tag = "1")]
pub block: ::core::option::Option<Block>,
/// The set of transaction changes observed in the specified block.
#[prost(message, repeated, tag = "2")]
pub changes: ::prost::alloc::vec::Vec<TransactionContractChanges>,
}
// This file contains the proto definitions for Substreams common to all integrations.
/// A struct describing a block.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Block {
/// The blocks hash.
#[prost(bytes = "vec", tag = "1")]
pub hash: ::prost::alloc::vec::Vec<u8>,
/// The parent blocks hash.
#[prost(bytes = "vec", tag = "2")]
pub parent_hash: ::prost::alloc::vec::Vec<u8>,
/// The block number.
#[prost(uint64, tag = "3")]
pub number: u64,
/// The block timestamp.
#[prost(uint64, tag = "4")]
pub ts: u64,
}
/// A struct describing a transaction.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Transaction {
/// The transaction hash.
#[prost(bytes = "vec", tag = "1")]
pub hash: ::prost::alloc::vec::Vec<u8>,
/// The sender of the transaction.
#[prost(bytes = "vec", tag = "2")]
pub from: ::prost::alloc::vec::Vec<u8>,
/// The receiver of the transaction.
#[prost(bytes = "vec", tag = "3")]
pub to: ::prost::alloc::vec::Vec<u8>,
/// The transactions index within the block.
/// TODO: should this be uint32? to match the type from the native substream type?
#[prost(uint64, tag = "4")]
pub index: u64,
}
/// A custom struct representing an arbitrary attribute of a protocol component.
/// This is mainly used by the native integration to track the necessary information about the protocol.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Attribute {
/// The name of the attribute.
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// The value of the attribute.
#[prost(bytes = "vec", tag = "2")]
pub value: ::prost::alloc::vec::Vec<u8>,
/// The type of change the attribute underwent.
#[prost(enumeration = "ChangeType", tag = "3")]
pub change: i32,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtocolType {
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
#[prost(enumeration = "FinancialType", tag = "2")]
pub financial_type: i32,
#[prost(message, repeated, tag = "3")]
pub attribute_schema: ::prost::alloc::vec::Vec<Attribute>,
#[prost(enumeration = "ImplementationType", tag = "4")]
pub implementation_type: i32,
}
/// A struct describing a part of the protocol.
///
/// Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair,
/// the component would represent a single contract. In case of VM integration, such component would
/// not need any attributes, because all the relevant info would be tracked via storage slots and balance changes.
/// It can also be a wrapping contract, like WETH, that has a constant price, but it allows swapping tokens.
/// This is why the name ProtocolComponent is used instead of "Pool" or "Pair".
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtocolComponent {
/// A unique identifier for the component within the protocol.
/// Can be e.g. a stringified address or a string describing the trading pair.
#[prost(string, tag = "1")]
pub id: ::prost::alloc::string::String,
/// Addresses of the ERC20 tokens used by the component.
#[prost(bytes = "vec", repeated, tag = "2")]
pub tokens: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
/// Addresses of the contracts used by the component.
/// Usually it is a single contract, but some protocols use multiple contracts.
#[prost(bytes = "vec", repeated, tag = "3")]
pub contracts: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
/// Static attributes of the component.
/// These attributes MUST be immutable. If it can ever change, it should be given as an EntityChanges for this component id.
/// The inner ChangeType of the attribute has to match the ChangeType of the ProtocolComponent.
#[prost(message, repeated, tag = "4")]
pub static_att: ::prost::alloc::vec::Vec<Attribute>,
/// Type of change the component underwent.
#[prost(enumeration = "ChangeType", tag = "5")]
pub change: i32,
/// / Represents the functionality of the component.
#[prost(message, optional, tag = "6")]
pub protocol_type: ::core::option::Option<ProtocolType>,
/// Transaction where this component was created
#[prost(message, optional, tag = "7")]
pub tx: ::core::option::Option<Transaction>,
}
/// A struct for following the changes of Total Value Locked (TVL) of a protocol component.
///
/// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole.
/// E.g. for UniswapV2 pair WETH/USDC, this tracks the USDC and WETH balance of the pair contract.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BalanceChange {
/// The address of the ERC20 token whose balance changed.
#[prost(bytes = "vec", tag = "1")]
pub token: ::prost::alloc::vec::Vec<u8>,
/// The new balance of the token. Note: it must be a big endian encoded int.
#[prost(bytes = "vec", tag = "2")]
pub balance: ::prost::alloc::vec::Vec<u8>,
/// The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded.
/// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded.
#[prost(bytes = "vec", tag = "3")]
pub component_id: ::prost::alloc::vec::Vec<u8>,
}
// Native entities
/// A component is a set of attributes that are associated with a custom entity.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EntityChanges {
/// A unique identifier of the entity within the protocol.
#[prost(string, tag = "1")]
pub component_id: ::prost::alloc::string::String,
/// The set of attributes that are associated with the entity.
#[prost(message, repeated, tag = "2")]
pub attributes: ::prost::alloc::vec::Vec<Attribute>,
}
// VM entities
/// A key value entry into contract storage.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ContractSlot {
/// A contract's storage slot.
#[prost(bytes = "vec", tag = "2")]
pub slot: ::prost::alloc::vec::Vec<u8>,
/// The new value for this storage slot.
#[prost(bytes = "vec", tag = "3")]
pub value: ::prost::alloc::vec::Vec<u8>,
}
/// Changes made to a single contract's state.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ContractChange {
/// The contract's address
#[prost(bytes = "vec", tag = "1")]
pub address: ::prost::alloc::vec::Vec<u8>,
/// The new balance of the contract, empty bytes indicates no change.
#[prost(bytes = "vec", tag = "2")]
pub balance: ::prost::alloc::vec::Vec<u8>,
/// The new code of the contract, empty bytes indicates no change.
#[prost(bytes = "vec", tag = "3")]
pub code: ::prost::alloc::vec::Vec<u8>,
/// The changes to this contract's slots, empty sequence indicates no change.
#[prost(message, repeated, tag = "4")]
pub slots: ::prost::alloc::vec::Vec<ContractSlot>,
/// Whether this is an update, a creation or a deletion.
#[prost(enumeration = "ChangeType", tag = "5")]
pub change: i32,
}
// Aggregate entities
/// A set of changes aggregated by transaction.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionChanges {
/// The transaction instance that results in the changes.
#[prost(message, optional, tag = "1")]
pub tx: ::core::option::Option<Transaction>,
/// Contains the changes induced by the above transaction, aggregated on a per-contract basis.
/// Contains the contract changes induced by the above transaction, usually for tracking VM components.
#[prost(message, repeated, tag = "2")]
pub contract_changes: ::prost::alloc::vec::Vec<ContractChange>,
/// Contains the entity changes induced by the above transaction.
/// Usually for tracking native components or used for VM extensions (plugins).
#[prost(message, repeated, tag = "3")]
pub entity_changes: ::prost::alloc::vec::Vec<EntityChanges>,
/// An array of newly added components.
#[prost(message, repeated, tag = "4")]
pub component_changes: ::prost::alloc::vec::Vec<ProtocolComponent>,
/// An array of balance changes to components.
#[prost(message, repeated, tag = "5")]
pub balance_changes: ::prost::alloc::vec::Vec<BalanceChange>,
}
/// A set of transaction changes within a single block.
/// This message must be the output of your substreams module.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockChanges {
/// The block for which these changes are collectively computed.
#[prost(message, optional, tag = "1")]
pub block: ::core::option::Option<Block>,
/// The set of transaction changes observed in the specified block.
#[prost(message, repeated, tag = "2")]
pub changes: ::prost::alloc::vec::Vec<TransactionChanges>,
}
/// Enum to specify the type of a change.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum ChangeType {
Unspecified = 0,
Update = 1,
Creation = 2,
Deletion = 3,
}
impl ChangeType {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
ChangeType::Unspecified => "CHANGE_TYPE_UNSPECIFIED",
ChangeType::Update => "CHANGE_TYPE_UPDATE",
ChangeType::Creation => "CHANGE_TYPE_CREATION",
ChangeType::Deletion => "CHANGE_TYPE_DELETION",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"CHANGE_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
"CHANGE_TYPE_UPDATE" => Some(Self::Update),
"CHANGE_TYPE_CREATION" => Some(Self::Creation),
"CHANGE_TYPE_DELETION" => Some(Self::Deletion),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum FinancialType {
Swap = 0,
Lend = 1,
Leverage = 2,
Psm = 3,
}
impl FinancialType {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
FinancialType::Swap => "SWAP",
FinancialType::Lend => "LEND",
FinancialType::Leverage => "LEVERAGE",
FinancialType::Psm => "PSM",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"SWAP" => Some(Self::Swap),
"LEND" => Some(Self::Lend),
"LEVERAGE" => Some(Self::Leverage),
"PSM" => Some(Self::Psm),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum ImplementationType {
Vm = 0,
Custom = 1,
}
impl ImplementationType {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
ImplementationType::Vm => "VM",
ImplementationType::Custom => "CUSTOM",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"VM" => Some(Self::Vm),
"CUSTOM" => Some(Self::Custom),
_ => None,
}
}
}
/// A message containing relative balance changes.
///
/// Used to track token balances of protocol components in case they are only
/// available as relative values within a block.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BalanceDelta {
/// The ordinal of the balance change. Must be unique & deterministic over all balances
/// changes within a block.
#[prost(uint64, tag = "1")]
pub ord: u64,
/// The tx hash of the transaction that caused the balance change.
#[prost(message, optional, tag = "2")]
pub tx: ::core::option::Option<Transaction>,
/// The address of the ERC20 token whose balance changed.
#[prost(bytes = "vec", tag = "3")]
pub token: ::prost::alloc::vec::Vec<u8>,
/// The delta balance of the token.
#[prost(bytes = "vec", tag = "4")]
pub delta: ::prost::alloc::vec::Vec<u8>,
/// The id of the component whose TVL is tracked.
/// If the protocol component includes multiple contracts, the balance change must be
/// aggregated to reflect how much tokens can be traded.
#[prost(bytes = "vec", tag = "5")]
pub component_id: ::prost::alloc::vec::Vec<u8>,
}
/// A set of balances deltas, usually a group of changes within a single block.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockBalanceDeltas {
#[prost(message, repeated, tag = "1")]
pub balance_deltas: ::prost::alloc::vec::Vec<BalanceDelta>,
}
/// A message containing protocol components that were created by a single tx.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionProtocolComponents {
#[prost(message, optional, tag = "1")]
pub tx: ::core::option::Option<Transaction>,
#[prost(message, repeated, tag = "2")]
pub components: ::prost::alloc::vec::Vec<ProtocolComponent>,
}
/// All protocol components that were created within a block with their corresponding tx.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockTransactionProtocolComponents {
#[prost(message, repeated, tag = "1")]
pub tx_components: ::prost::alloc::vec::Vec<TransactionProtocolComponents>,
}
// @@protoc_insertion_point(module)

View File

@@ -0,0 +1,71 @@
specVersion: v0.1.0
package:
name: "ethereum_sfrax"
version: v0.1.0
protobuf:
files:
- tycho/evm/v1/vm.proto
- tycho/evm/v1/common.proto
- tycho/evm/v1/utils.proto
importPaths:
- ../../proto
- ./proto
binaries:
default:
type: wasm/rust-v1
file: ../target/wasm32-unknown-unknown/release/ethereum_sfrax.wasm
modules:
- name: map_components
kind: map
initialBlock: 18378085
inputs:
- params: string
- source: sf.ethereum.type.v2.Block
output:
type: proto:tycho.evm.v1.BlockTransactionProtocolComponents
doc: |
param is the address without the 0x prefix of the sfrax vault you want to track
- name: store_components
kind: store
initialBlock: 18378085
updatePolicy: add
valueType: int64
inputs:
- map: map_components
- name: store_balances
kind: store
initialBlock: 18378085
updatePolicy: add
valueType: bigint
inputs:
- map: map_relative_balances
- name: map_relative_balances
kind: map
initialBlock: 18378085
inputs:
- source: sf.ethereum.type.v2.Block
- store: store_components
output:
type: proto:tycho.evm.v1.BlockBalanceDeltas
- name: map_protocol_changes
kind: map
initialBlock: 18378085
inputs:
- source: sf.ethereum.type.v2.Block
- map: map_components
- map: map_relative_balances
- store: store_components
- store: store_balances
mode: deltas
output:
type: proto:tycho.evm.v1.BlockChanges
params:
map_components: "A663B02CF0a4b149d2aD41910CB81e23e1c41c32"