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§
Sourcefn fee(&self) -> f64
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.
Sourcefn spot_price(
&self,
base: &Token,
quote: &Token,
) -> Result<f64, SimulationError>
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.
Sourcefn get_amount_out(
&self,
amount_in: BigUint,
token_in: &Token,
token_out: &Token,
) -> Result<GetAmountOutResult, SimulationError>
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.
Sourcefn get_limits(
&self,
sell_token: Bytes,
buy_token: Bytes,
) -> Result<(BigUint, BigUint), SimulationError>
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 soldbuy_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
Sourcefn delta_transition(
&mut self,
delta: ProtocolStateDelta,
tokens: &HashMap<Bytes, Token>,
balances: &Balances,
) -> Result<(), TransitionError<String>>
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- AProtocolStateDeltafrom the tycho indexer
§Returns
Result<(), TransitionError<String>>- AResultcontaining()on success or aTransitionErroron failure.
Sourcefn clone_box(&self) -> Box<dyn ProtocolSim>
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>.
Sourcefn as_any_mut(&mut self) -> &mut dyn Any
fn as_any_mut(&mut self) -> &mut dyn Any
Allows downcasting of the trait object to its mutable underlying type.
Sourcefn eq(&self, other: &dyn ProtocolSim) -> bool
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§
Sourcefn swap_to_price(
&self,
token_in: &Bytes,
token_out: &Bytes,
target_price: Price,
) -> Result<Trade, SimulationError>
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 aPricestruct 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)- ATradestruct 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).
Sourcefn query_supply(
&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>
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 aPricestruct 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)- ATradestruct containing the largest trade that can be executed on this pool while respecting the provided trace priceErr(SimulationError)- If:- The calculation encounters numerical issues
- The method is not implemented for this protocol
Sourcefn as_indicatively_priced(
&self,
) -> Result<&dyn IndicativelyPriced, SimulationError>
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>
impl Clone for Box<dyn ProtocolSim>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more