Skip to main content

RawPoolState

Struct RawPoolState 

Source
pub struct RawPoolState {
Show 15 fields pub variant: CurveVariant, pub balances: Vec<U256>, pub token_decimals: Vec<u8>, pub amp: U256, pub fee: Option<U256>, pub mid_fee: Option<U256>, pub out_fee: Option<U256>, pub fee_gamma: Option<U256>, pub offpeg_fee_multiplier: Option<U256>, pub price_scale: Option<Vec<U256>>, pub d: Option<U256>, pub gamma: Option<U256>, pub dynamic_rates: Option<Vec<Option<U256>>>, pub precisions: Option<Vec<U256>>, pub eth_variant: Option<bool>,
}
Expand description

Raw on-chain pool state, as collected by a transport (RPC, Substreams, etc.).

The consumer fills in the fields relevant to the pool’s CurveVariant, then calls build_pool to get a crate::evm::protocol::curve::math::Pool ready for swap computation.

Fields§

§variant: CurveVariant

Which Curve variant this pool is.

§balances: Vec<U256>

Token balances in native token units (wei). Updates every block.

Length determines coin count (2, 3, or 4+).

§Gotchas

StableSwapNG: balances(i) on-chain returns balanceOf(pool) - admin_balances[i], excluding uncollected admin fees. An indexer tracking ERC20 Transfer events sees balanceOf changes, not balances(). The difference is small but causes wei-level mismatches. Use the balances() getter, not balanceOf.

Rebase tokens (e.g. stETH): balances change without Transfer events — the token rebases in-place. Requires calling balanceOf(pool) on the rebase token each block.

§token_decimals: Vec<u8>

Token decimals for each coin (e.g. [18, 6] for ETH/USDC). Must have the same length as balances.

§amp: U256

Amplification parameter — already interpolated for the target block. Semi-static: only changes during A ramping (rare admin events, days apart).

This value must match what the on-chain _A() internal function returns at the target block’s timestamp. It includes the variant’s precision scaling (A_PRECISION=100 for StableSwap V2+, A_MULTIPLIER=10000 for CryptoSwap, 1 for V0/V1).

§How to obtain this value

RPC consumer: Call the pool’s A() view function at the target block. Returns the already-interpolated value in a single RPC call.

let amp = pool_contract.A().block(block_number).call().await?;

Warning: for all A_PRECISION=100 variants (V2, Meta, NG, ALend), A() returns initial_A / A_PRECISION via integer division, losing the remainder:

initial_A = 79258
A() = 79258 / 100 = 792      (truncated)
A() * 100 = 79200 ≠ 79258    (lost 58)

For exact precision, read initial_A() directly when no ramping (initial_A == future_A), or use interpolate_a during ramps.

Substreams / storage-based consumer: Read initial_A, future_A, initial_A_time, future_A_time from contract storage, then interpolate for the current block’s timestamp:

let amp = curve_adapter::interpolate_a(
    initial_a, future_a,
    initial_a_time, future_a_time,
    block_timestamp,
);

For V0/V1 pools that store a single A value (no ramping), pass that value directly.

Caution with factory deploy events: PlainPoolDeployed and MetaPoolDeployed events emit A as the user-provided value (e.g. 400), NOT the raw on-chain value (e.g. 40000). Multiply by A_PRECISION (100 for V2/NG/Meta/ALend) before passing here.

§fee: Option<U256>

StableSwap fee. Static (set at pool creation). Required for all StableSwap variants.

§mid_fee: Option<U256>

CryptoSwap mid fee. Static. Required for all CryptoSwap variants.

§out_fee: Option<U256>

CryptoSwap out fee. Static. Required for all CryptoSwap variants.

§fee_gamma: Option<U256>

CryptoSwap fee gamma. Static. Required for all CryptoSwap variants.

§offpeg_fee_multiplier: Option<U256>

Dynamic fee multiplier. Static. Required for StableSwapNG and StableSwapALend.

§price_scale: Option<Vec<U256>>

Price scale(s). Updates every block. TwoCrypto: 1 element, TriCrypto: 2 elements. Required for all CryptoSwap variants.

§d: Option<U256>

Pool invariant D. Updates every block. Required for all CryptoSwap variants.

§gamma: Option<U256>

Gamma parameter. Semi-static (only changes during admin ramp). Required for TwoCryptoV1, TwoCryptoNG, TriCryptoV1, TriCryptoNG. NOT required for TwoCryptoStable (gamma is ignored).

§dynamic_rates: Option<Vec<Option<U256>>>

Per-token dynamic rates for StableSwap variants. Depends on token type.

If None, rates are computed from token_decimals as 10^(36 - decimals). This is correct for v6+ crvUSD factory pools (balances variant) which use static decimal-based rates and have no stored_rates() getter.

If Some, must have the same length as balances. Each element:

  • Some(rate) — use this dynamic rate (oracle, ERC4626, etc.)
  • None — compute from decimals as 10^(36 - decimals)

§When to provide dynamic rates

StableSwapNG with oracle tokens: Call stored_rates() on the pool contract each block. Plain tokens return static rates, but ERC4626/oracle tokens return rates that change per-block.

MetaPools: rates[last] must be base_pool.get_virtual_price(). To find the base pool address: try pool.base_pool() first. MetaPool Factory proxy pools lack this getter — use factory.get_base_pool(pool) instead. Do not assume the base pool is 3pool; BTC meta pools use sBTC.

§Gotchas

Fee-on-transfer tokens: actual received amount differs from the transfer parameter. Curve pools generally do not support these tokens, but if encountered, balances will be incorrect.

Tokens with 0 decimals: rate becomes 10^36 — valid but rounding impact is outsized. Every wei of such a token is worth 10^36 in normalized space.

§precisions: Option<Vec<U256>>

On-chain precisions for CryptoSwap variants. Immutable.

If Some, used directly instead of computing from token_decimals. Read from the pool contract’s precisions() getter.

This is important because some tokens report incorrect decimals() (e.g. Spectra PT tokens), and the factory computes the correct precisions at deployment time.

If None, precisions are computed as 10^(18 - decimals).

§eth_variant: Option<bool>

Selects the deployed Vyper flavour for TwoCryptoV1 only. Immutable.

Legacy 2-coin CryptoSwap V1 pools ship in two flavours whose Newton get_y solver differs by a single mul2 integer-division grouping (see [crate::evm::protocol::curve::math::core::twocrypto_v1]). Some(true) selects the ETH pool grouping (all factory/proxy and WETH-paired legacy pools); Some(false) selects the non-ETH legacy direct-deploy grouping.

Required for TwoCryptoV1build_pool returns BuildError::MissingField if it is None. Ignored for every other variant. Obtain it via detect_eth_variant.

Trait Implementations§

Source§

impl Clone for RawPoolState

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for RawPoolState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RawPoolState

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for RawPoolState

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for RawPoolState

Source§

impl PartialEq for RawPoolState

Source§

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

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for RawPoolState

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for RawPoolState

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<'de, T> BorrowedRpcObject<'de> for T
where T: RpcBorrow<'de> + RpcSend,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<'de, T> RpcBorrow<'de> for T
where T: Deserialize<'de> + Debug + Send + Sync + Unpin,

Source§

impl<T> RpcObject for T
where T: RpcSend + RpcRecv,

Source§

impl<T> RpcRecv for T
where T: DeserializeOwned + Debug + Send + Sync + Unpin + 'static,

Source§

impl<T> RpcSend for T
where T: Serialize + Clone + Debug + Send + Sync + Unpin,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more