Sfraxeth adapter and substream with SDK integration (#87)

* first commit

* feat: implemented get tokens and improved modifier

* feat: added missing functions (to implement)

* feat: implemented getPoolIds

* feat: implemented getCapabilities

* feat: implemented getLimits function

* fix: fixed constructor

* feat and fix: implemented testGetLimitsFraxEthV3 and fixed getLimits

* feat: implementing getPriceAt function

* feat and fix: finished implementing getPriceAt, fixed modifier

* feat: price function and tests implemented

* fix: removed onlySupportedTokens modifier from getPriceAt and applied it in price and swap function

* feat: implemented sell, buy, and swap functions

* implementing final tests

* aligned with main branch

* fixes

* fix: Review Fixes

* feat: 🎨 sfraxeth substream initial scaffolding

* fix: 🎨 protocol component creation at deployment block

* build: 💚 cargo build

* feat: 🎨 map proper event to balance changes

* fix: 🚚 remove unnecessary files

* fix: 💚 ci checks

Due to the CI checks requiring the latest rust nightly, the rust-lang organisation
introduced new doc related rules. This commit fixes the CI errors by making
the necessary changes to the comments in substreams-balancer comments

* fix: 🐛 wasm output name

* fix: 🐛 update starting block = deployment block -1

* feat: 🎨 add store for reward cycles and update balances accounting after after deposit before Withdraw

* feat: 🎨 finish setting up block reward logic

* docs: 📝 add comments on extra module

* build: 📌 adapt dependencies to workspace dependencies

setting prost-types to workspace version causes build errors

* feat: 🎨 add support for several EVM compatible networks

* fix: 🐛 update balance delta accounting logic following the `NextRewardCycle` event only

* fix: 🐛 hex address string param encoding

* fix: 🐛 deployment transaction check

* ci: 💚 ci check passing

* fix: 🐛 issues with hex-binary encoding

* refactor: ♻️ address mappings for various networks

* fix: 💚 formatting

* feat: Implemented testPoolBehaviour

* chore: Removed unused comments

* feat: ⬆️ update to recent sdk

* feat: 🎨 testing setup

* test:  setup test environminte for sfraxeth

* fix: 🐛 unwrap error in map_protocol_changes

* build: ⬆️ update rust version

* build:  remove unnecessary deps

* build: 🚚 remove unnecessary pb/tycho

* fix: 🐛 remove balance owner attribute

* fix: 🐛 remove unnecessary static attributes

* fix: 🐛 remove manual updates

* fix: 🔥 remove unused data model from contract.proto

* fix: 🐛 filter by known components

* feat:  use store delta for reward change accounting

* refactor: ♻️ remove shallow create vault component

* feat:  replace is_deployment_tx logic with simpler txn match

* test:  manual testing with inspection against etherscan

https://etherscan.io/address/0xac3E018457B222d93114458476f3E3416Abbe38F#events

* ci: 💚 ci checks

* fix: 🐛 map_protocol_components output data

* fix: 🐛 output type on map_protocol_changes

* test: 🧪 skip balance checks

* fixed FraxV3FrxEthAdapter arguments for constructor in manifest.yaml

* fix: 🐛 adapter error with overflow/underflow and addresses

* restore: restored previous adater version

* fix: set minimum swap amount to prevent overflow/underflow

* fix: set minimum swap amount only for sfrxETH -> frxETH

* improve: added print block_number to runner.py when get_amout_out fails

* removed console.log

* alignment with propeller main

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

* installed protosim_py 0.21.0

* commented out minimum swap amount for sfrxEth -> frxEth pair

* updated adapter limits

* working on fixes

* fix: Adjust getLimits according to protocol limitation.

Previously limits were estimated with token supplies, this commit simplifies limits and adjusts them so they correspond closely with what is supported by the sfrxETH contract.

* chore: fmt

* wip: Changed ubuntu to 20.04, fmt adapters

* wip: Updated python tests

* wip: Trying with ubuntu: latest

* chore: fmt adapters

* wip: Using ubuntu 20.04

* chore: Switched back to ubuntu-latest

---------

Co-authored-by: Ignazio Bovo <ignazio@jsgenesis.com>
Co-authored-by: domenicodev <domenico.romeo3919@gmail.com>
Co-authored-by: kayibal <alan@datarevenue.com>
Co-authored-by: domenicodev <domenico.rom3@gmail.com>
This commit is contained in:
Mattia Papa
2024-10-23 15:17:45 +02:00
committed by GitHub
parent 0dda680ab2
commit 3013cd9bfd
26 changed files with 7256 additions and 79 deletions

View File

@@ -6,16 +6,16 @@
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Block {
/// The blocks hash.
#[prost(bytes="vec", tag="1")]
#[prost(bytes = "vec", tag = "1")]
pub hash: ::prost::alloc::vec::Vec<u8>,
/// The parent blocks hash.
#[prost(bytes="vec", tag="2")]
#[prost(bytes = "vec", tag = "2")]
pub parent_hash: ::prost::alloc::vec::Vec<u8>,
/// The block number.
#[prost(uint64, tag="3")]
#[prost(uint64, tag = "3")]
pub number: u64,
/// The block timestamp.
#[prost(uint64, tag="4")]
#[prost(uint64, tag = "4")]
pub ts: u64,
}
/// A struct describing a transaction.
@@ -24,96 +24,102 @@ pub struct Block {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Transaction {
/// The transaction hash.
#[prost(bytes="vec", tag="1")]
#[prost(bytes = "vec", tag = "1")]
pub hash: ::prost::alloc::vec::Vec<u8>,
/// The sender of the transaction.
#[prost(bytes="vec", tag="2")]
#[prost(bytes = "vec", tag = "2")]
pub from: ::prost::alloc::vec::Vec<u8>,
/// The receiver of the transaction.
#[prost(bytes="vec", tag="3")]
#[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")]
#[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.
/// 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")]
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// The value of the attribute.
#[prost(bytes="vec", tag="2")]
#[prost(bytes = "vec", tag = "2")]
pub value: ::prost::alloc::vec::Vec<u8>,
/// The type of change the attribute underwent.
#[prost(enumeration="ChangeType", tag="3")]
#[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")]
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
#[prost(enumeration="FinancialType", tag="2")]
#[prost(enumeration = "FinancialType", tag = "2")]
pub financial_type: i32,
#[prost(message, repeated, tag="3")]
#[prost(message, repeated, tag = "3")]
pub attribute_schema: ::prost::alloc::vec::Vec<Attribute>,
#[prost(enumeration="ImplementationType", tag="4")]
#[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".
///
/// 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")]
#[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")]
#[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")]
#[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")]
#[prost(message, repeated, tag = "4")]
pub static_att: ::prost::alloc::vec::Vec<Attribute>,
/// Type of change the component underwent.
#[prost(enumeration="ChangeType", tag="5")]
#[prost(enumeration = "ChangeType", tag = "5")]
pub change: i32,
/// / Represents the functionality of the component.
#[prost(message, optional, tag="6")]
#[prost(message, optional, tag = "6")]
pub protocol_type: ::core::option::Option<ProtocolType>,
/// Transaction where this component was created
#[prost(message, optional, tag="7")]
#[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.
///
/// 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")]
#[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")]
#[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")]
/// 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
@@ -123,10 +129,10 @@ pub struct BalanceChange {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EntityChanges {
/// A unique identifier of the entity within the protocol.
#[prost(string, tag="1")]
#[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")]
#[prost(message, repeated, tag = "2")]
pub attributes: ::prost::alloc::vec::Vec<Attribute>,
}
// VM entities
@@ -136,10 +142,10 @@ pub struct EntityChanges {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ContractSlot {
/// A contract's storage slot.
#[prost(bytes="vec", tag="2")]
#[prost(bytes = "vec", tag = "2")]
pub slot: ::prost::alloc::vec::Vec<u8>,
/// The new value for this storage slot.
#[prost(bytes="vec", tag="3")]
#[prost(bytes = "vec", tag = "3")]
pub value: ::prost::alloc::vec::Vec<u8>,
}
/// Changes made to a single contract's state.
@@ -147,19 +153,19 @@ pub struct ContractSlot {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ContractChange {
/// The contract's address
#[prost(bytes="vec", tag="1")]
#[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")]
#[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")]
#[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")]
#[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")]
#[prost(enumeration = "ChangeType", tag = "5")]
pub change: i32,
}
// Aggregate entities
@@ -169,21 +175,22 @@ pub struct ContractChange {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionChanges {
/// The transaction instance that results in the changes.
#[prost(message, optional, tag="1")]
#[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")]
/// 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")]
#[prost(message, repeated, tag = "3")]
pub entity_changes: ::prost::alloc::vec::Vec<EntityChanges>,
/// An array of newly added components.
#[prost(message, repeated, tag="4")]
#[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")]
#[prost(message, repeated, tag = "5")]
pub balance_changes: ::prost::alloc::vec::Vec<BalanceChange>,
}
/// A set of transaction changes within a single block.
@@ -192,10 +199,10 @@ pub struct TransactionChanges {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockChanges {
/// The block for which these changes are collectively computed.
#[prost(message, optional, tag="1")]
#[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")]
#[prost(message, repeated, tag = "2")]
pub changes: ::prost::alloc::vec::Vec<TransactionChanges>,
}
/// Enum to specify the type of a change.
@@ -295,15 +302,15 @@ impl ImplementationType {
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionEntityChanges {
#[prost(message, optional, tag="1")]
#[prost(message, optional, tag = "1")]
pub tx: ::core::option::Option<Transaction>,
#[prost(message, repeated, tag="2")]
#[prost(message, repeated, tag = "2")]
pub entity_changes: ::prost::alloc::vec::Vec<EntityChanges>,
/// An array of newly added components.
#[prost(message, repeated, tag="3")]
#[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")]
#[prost(message, repeated, tag = "4")]
pub balance_changes: ::prost::alloc::vec::Vec<BalanceChange>,
}
/// A set of transaction changes within a single block.
@@ -311,10 +318,10 @@ pub struct TransactionEntityChanges {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockEntityChanges {
/// The block for which these changes are collectively computed.
#[prost(message, optional, tag="1")]
#[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")]
#[prost(message, repeated, tag = "2")]
pub changes: ::prost::alloc::vec::Vec<TransactionEntityChanges>,
}
/// A message containing relative balance changes.
@@ -326,44 +333,44 @@ pub struct BlockEntityChanges {
pub struct BalanceDelta {
/// The ordinal of the balance change. Must be unique & deterministic over all balances
/// changes within a block.
#[prost(uint64, tag="1")]
#[prost(uint64, tag = "1")]
pub ord: u64,
/// The tx hash of the transaction that caused the balance change.
#[prost(message, optional, tag="2")]
#[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")]
#[prost(bytes = "vec", tag = "3")]
pub token: ::prost::alloc::vec::Vec<u8>,
/// The delta balance of the token.
#[prost(bytes="vec", tag="4")]
#[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")]
#[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")]
#[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")]
#[prost(message, optional, tag = "1")]
pub tx: ::core::option::Option<Transaction>,
#[prost(message, repeated, tag="2")]
#[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")]
#[prost(message, repeated, tag = "1")]
pub tx_components: ::prost::alloc::vec::Vec<TransactionProtocolComponents>,
}
// WARNING: DEPRECATED. Please use common.proto's TransactionChanges and BlockChanges instead.
@@ -374,16 +381,16 @@ pub struct BlockTransactionProtocolComponents {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionContractChanges {
/// The transaction instance that results in the changes.
#[prost(message, optional, tag="1")]
#[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")]
#[prost(message, repeated, tag = "2")]
pub contract_changes: ::prost::alloc::vec::Vec<ContractChange>,
/// An array of newly added components.
#[prost(message, repeated, tag="3")]
#[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")]
#[prost(message, repeated, tag = "4")]
pub balance_changes: ::prost::alloc::vec::Vec<BalanceChange>,
}
/// A set of transaction changes within a single block.
@@ -391,10 +398,10 @@ pub struct TransactionContractChanges {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BlockContractChanges {
/// The block for which these changes are collectively computed.
#[prost(message, optional, tag="1")]
#[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")]
#[prost(message, repeated, tag = "2")]
pub changes: ::prost::alloc::vec::Vec<TransactionContractChanges>,
}
// @@protoc_insertion_point(module)