ProtocolSim

Trait ProtocolSim 

Source
pub trait ProtocolSim:
    Debug
    + Send
    + Sync
    + 'static {
    // Required methods
    fn fee(&self) -> f64;
    fn spot_price(
        &self,
        base: &Token,
        quote: &Token,
    ) -> Result<f64, SimulationError>;
    fn get_amount_out(
        &self,
        amount_in: BigUint,
        token_in: &Token,
        token_out: &Token,
    ) -> Result<GetAmountOutResult, SimulationError>;
    fn get_limits(
        &self,
        sell_token: Bytes,
        buy_token: Bytes,
    ) -> Result<(BigUint, BigUint), SimulationError>;
    fn delta_transition(
        &mut self,
        delta: ProtocolStateDelta,
        tokens: &HashMap<Bytes, Token>,
        balances: &Balances,
    ) -> Result<(), TransitionError<String>>;
    fn clone_box(&self) -> Box<dyn ProtocolSim>;
    fn as_any(&self) -> &dyn Any;
    fn as_any_mut(&mut self) -> &mut dyn Any;
    fn eq(&self, other: &dyn ProtocolSim) -> bool;

    // Provided methods
    fn swap_to_price(
        &self,
        token_in: &Bytes,
        token_out: &Bytes,
        target_price: Price,
    ) -> Result<Trade, SimulationError> { ... }
    fn query_supply(
        &self,
        token_in: &Bytes,
        token_out: &Bytes,
        target_price: Price,
    ) -> Result<Trade, SimulationError> { ... }
    fn as_indicatively_priced(
        &self,
    ) -> Result<&dyn IndicativelyPriced, SimulationError> { ... }
}
Expand description

ProtocolSim trait This trait defines the methods that a protocol state must implement in order to be used in the trade simulation.

Required Methods§

Source

fn fee(&self) -> f64

Returns the fee of the protocol as ratio

E.g. if the fee is 1%, the value returned would be 0.01.

Source

fn spot_price( &self, base: &Token, quote: &Token, ) -> Result<f64, SimulationError>

Returns the protocol’s current spot price of two tokens

Currency pairs are meant to be compared against one another in order to understand how much of the quote currency is required to buy one unit of the base currency.

E.g. if ETH/USD is trading at 1000, we need 1000 USD (quote) to buy 1 ETH (base currency).

§Arguments
  • a - Base Token: refers to the token that is the quantity of a pair. For the pair BTC/USDT, BTC would be the base asset.
  • b - Quote Token: refers to the token that is the price of a pair. For the symbol BTC/USDT, USDT would be the quote asset.
Source

fn get_amount_out( &self, amount_in: BigUint, token_in: &Token, token_out: &Token, ) -> Result<GetAmountOutResult, SimulationError>

Returns the amount out given an amount in and input/output tokens.

§Arguments
  • amount_in - The amount in of the input token.
  • token_in - The input token ERC20 token.
  • token_out - The output token ERC20 token.
§Returns

A Result containing a GetAmountOutResult struct on success or a SimulationError on failure.

Source

fn get_limits( &self, sell_token: Bytes, buy_token: Bytes, ) -> Result<(BigUint, BigUint), SimulationError>

Computes the maximum amount that can be traded between two tokens.

This function calculates the maximum possible trade amount between two tokens, taking into account the protocol’s specific constraints and mechanics. The implementation details vary by protocol - for example:

  • For constant product AMMs (like Uniswap V2), this is based on available reserves
  • For concentrated liquidity AMMs (like Uniswap V3), this considers liquidity across tick ranges

Note: if there are no limits, the returned amount will be a “soft” limit, meaning that the actual amount traded could be higher but it’s advised to not exceed it.

§Arguments
  • sell_token - The address of the token being sold
  • buy_token - The address of the token being bought
§Returns
  • Ok((Option<BigUint>, Option<BigUint>)) - A tuple containing:
    • First element: The maximum input amount
    • Second element: The maximum output amount

This means that for let res = get_limits(...) the amount input domain for get_amount_out would be [0, res.0] and the amount input domain for get_amount_in would be [0, res.1]

  • Err(SimulationError) - If any unexpected error occurs
Source

fn delta_transition( &mut self, delta: ProtocolStateDelta, tokens: &HashMap<Bytes, Token>, balances: &Balances, ) -> Result<(), TransitionError<String>>

Decodes and applies a protocol state delta to the state

Will error if the provided delta is missing any required attributes or if any of the attribute values cannot be decoded.

§Arguments
  • delta - A ProtocolStateDelta from the tycho indexer
§Returns
  • Result<(), TransitionError<String>> - A Result containing () on success or a TransitionError on failure.
Source

fn clone_box(&self) -> Box<dyn ProtocolSim>

Clones the protocol state as a trait object. This allows the state to be cloned when it is being used as a Box<dyn ProtocolSim>.

Source

fn as_any(&self) -> &dyn Any

Allows downcasting of the trait object to its underlying type.

Source

fn as_any_mut(&mut self) -> &mut dyn Any

Allows downcasting of the trait object to its mutable underlying type.

Source

fn eq(&self, other: &dyn ProtocolSim) -> bool

Compares two protocol states for equality. This method must be implemented to define how two protocol states are considered equal (used for tests).

Provided Methods§

Source

fn swap_to_price( &self, token_in: &Bytes, token_out: &Bytes, target_price: Price, ) -> Result<Trade, SimulationError>

Calculates the amount of token_in required to move the pool’s marginal price down to a target price, and the amount of token_out received.

§Arguments
  • token_in - The address of the token being sold (swapped into the pool)
  • token_out - The address of the token being bought (swapped out of the pool)
  • target_price - The target marginal price as a Price struct representing token_out per token_in (token_out/token_in) net of all fees:
    • numerator: Amount of token_out (what the pool offers)
    • denominator: Amount of token_in (what the pool wants)
    • The pool’s price will move down to this level as token_in is sold into it
§Returns
  • Ok(Trade) - A Trade struct containing the amount that needs to be swapped on the pool to move its price to target_price.
  • Err(SimulationError) - If:
    • The calculation encounters numerical issues (overflow, division by zero, etc.)
    • The method is not implemented for this protocol
§Edge Cases and Limitations
§Exact Price Achievement

It is almost never possible to achieve the target price exactly, only within some margin of tolerance. This is due to:

  • Discrete liquidity: For concentrated liquidity protocols (e.g., Uniswap V3), liquidity is distributed across discrete price ticks, making exact price targeting impossible
  • Numerical precision: Integer arithmetic and rounding may prevent exact price matching
  • Protocol constraints: Some protocols have minimum trade sizes or other constraints
§Unreachable Prices

If the target price is already below the current spot price (i.e., the price would need to move in the wrong direction), implementations typically return a zero trade (Trade with amount_in = 0 and amount_out = 0).

Source

fn query_supply( &self, token_in: &Bytes, token_out: &Bytes, target_price: Price, ) -> Result<Trade, SimulationError>

Calculates the maximum amount of token_out (sell token) a pool can supply, and the corresponding demanded amount of token_in (buy token), while respecting a minimum trade price.

§Arguments
  • token_in - The address of the token being bought by the pool (the buy token)
  • token_out - The address of the token being sold by the pool (the sell token)
  • target_price - The minimum acceptable price as a Price struct representing token_out per token_in (token_out/token_in) net of all fees:
    • numerator: Amount of token_out (what the pool offers)
    • denominator: Amount of token_in (what the pool wants)
    • The pool will supply token_out down to this price level
§Returns
  • Ok(Trade) - A Trade struct containing the largest trade that can be executed on this pool while respecting the provided trace price
  • Err(SimulationError) - If:
    • The calculation encounters numerical issues
    • The method is not implemented for this protocol
Source

fn as_indicatively_priced( &self, ) -> Result<&dyn IndicativelyPriced, SimulationError>

Cast as IndicativelyPriced. This is necessary for RFQ protocols

Trait Implementations§

Source§

impl Clone for Box<dyn ProtocolSim>

Source§

fn clone(&self) -> Box<dyn ProtocolSim>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Implementors§