Skip to main content

Entrypoints

This section outlines the core entrypoints for the Invariant program, providing developers with essential methods to interact with the protocol. These entrypoints cover various aspects of the contract, including protocol fee management, fee tier administration, pool creation and management, position handling, and swap functionality. Program has 3 main entrypoints(Init, Handle, State). Invariant specific entrypoints are reached by sending a message with a proper enum variant to either Handle or State entrypoint. It should be noted that the message types for those entrypoints differ and can't be used interchangeably.

Init Entrypoint

Corresponding method

#[async_init]
async fn init()

Input

pub struct InitInvariant {
pub config: InvariantConfig,
}

This entrypoint initializes the program with the specified protocol fee and administrator ActorId.

Input parameters

NameTypeDescription
configInvariantConfigConfig for the program

State Entrypoint

Corresponding method

#[no_mangle]
extern "C" fn state()

This entrypoint is used for methods that don't alter the state.

Invariant entrypoints can be accessed with variants of the InvariantStateQuery enum.

pub enum InvariantStateQuery {
FeeTierExist(FeeTier),
GetFeeTiers,
GetProtocolFee,
GetPool(ActorId, ActorId, FeeTier),
GetPools(u8, u16),
GetPosition(ActorId, u32),
GetTick(PoolKey, i32),
IsTickInitialized(PoolKey, i32),
GetAllPositions(ActorId),
}

Entrypoint return messages are variants of InvariantStateReply enum.

pub enum InvariantStateReply {
ProtocolFee(Percentage),
QueriedFeeTiers(Vec<FeeTier>),
FeeTierExist(bool),
Pool(Pool),
Pools(Vec<PoolKey>),
Position(Position),
Positions(Vec<Position>),
Tick(Tick),
IsTickInitialized(bool),
QueryFailed(InvariantError),
}

Errors

Errors are returned through the QueryFailed variant.

Handle Entrypoint

Corresponding method

#[async_main]
async fn main()

This entrypoint is used for methods that don't alter the state.

Invariant entrypoints can be accessed with variants of the InvariantAction enum.

Input

pub enum InvariantAction {
ChangeProtocolFee(Percentage),
AddFeeTier(FeeTier),
RemoveFeeTier(FeeTier),
CreatePool {
token_0: ActorId,
token_1: ActorId,
fee_tier: FeeTier,
init_sqrt_price: SqrtPrice,
init_tick: i32,
},
ChangeFeeReceiver(PoolKey, ActorId),
CreatePosition {
pool_key: PoolKey,
lower_tick: i32,
upper_tick: i32,
liquidity_delta: Liquidity,
slippage_limit_lower: SqrtPrice,
slippage_limit_upper: SqrtPrice,
},
RemovePosition {
position_id: u32,
},
TransferPosition {
index: u32,
receiver: ActorId,
},
Swap {
pool_key: PoolKey,
x_to_y: bool,
amount: TokenAmount,
by_amount_in: bool,
sqrt_price_limit: SqrtPrice,
},
Quote {
pool_key: PoolKey,
x_to_y: bool,
amount: TokenAmount,
by_amount_in: bool,
sqrt_price_limit: SqrtPrice,
},
QuoteRoute {
amount_in: TokenAmount,
swaps: Vec<SwapHop>,
},
ClaimFee {
position_id: u32,
},
WithdrawProtocolFee(PoolKey),
}

Output

Entrypoint return messages are variants of InvariantEvent enum.

pub enum InvariantEvent {
ProtocolFeeChanged(Percentage),
PositionCreatedReturn(Position),
PositionCreatedEvent {
block_timestamp: u64,
address: ActorId,
pool_key: PoolKey,
liquidity_delta: Liquidity,
lower_tick: i32,
upper_tick: i32,
current_sqrt_price: SqrtPrice,
},
PositionRemovedReturn(TokenAmount, TokenAmount),
PositionRemovedEvent {
block_timestamp: u64,
caller: ActorId,
pool_key: PoolKey,
liquidity: Liquidity,
lower_tick_index: i32,
upper_tick_index: i32,
sqrt_price: SqrtPrice,
},
CrossTickEvent {
timestamp: u64,
address: ActorId,
pool: PoolKey,
indexes: Vec<i32>,
},
SwapEvent {
timestamp: u64,
address: ActorId,
pool: PoolKey,
amount_in: TokenAmount,
amount_out: TokenAmount,
fee: TokenAmount,
start_sqrt_price: SqrtPrice,
target_sqrt_price: SqrtPrice,
x_to_y: bool,
},
SwapReturn(CalculateSwapResult),
Quote(QuoteResult),
ClaimFee(TokenAmount, TokenAmount),
QuoteRoute(TokenAmount),
ActionFailed(InvariantError),
}

Errors

Errors are returned through panic!

Invariant specific entrypoints

This section describes invariant specific entrypoints.

Protocol fee

Get protocol fee

This method retrieves the current protocol fee percentage.

Entrypoint

State

Input

InvariantStateQuery::GetProtocolFee

Output

InvariantStateReply::ProtocolFee(Percentage)

Output parameters

TypeDescription
PercentageThe current protocol fee.

Withdraw protocol fee

This operation enables the withdrawal of protocol fees associated with a specific pool, based on the provided pool key. The withdrawn funds are sent to the fee receiver wallet. Please note that this action can only be performed by fee receiver.

Entrypoint

Handle

Input

InvariantAction::WithdrawProtocolFee(PoolKey)

Input parameters

TypeDescription
PoolKeyThe pool key that corresponds to the withdrawal of fees from the associated pool.

Errors

CodeDescription
NotFeeReceiverReverts the call when the caller is unauthorized receiver.
TransferErrorFails if the allowance is insufficient or the user balance transfer fails
NotEnoughGasToExecuteOccurs when provided gas was too low to execute

External Contracts

  • GRC-20

Change protocol fee

This function allows for the adjustment of the current protocol fee percentage. Note that this operation is restricted to administrators.

Entrypoint

Handle

Input

InvariantAction::ChangeProtocolFee(Percentage)

Output

InvariantEvent::ProtocolFeeChanged(Percentage)

Input parameters

TypeDescription
PercentageThe new protocol fee percentage.

Output parameters

TypeDescription
PercentageUpdated protocol fee percentage.

Errors

CodeDescription
NotAdminReverts the call when the caller is an unauthorized user.

Change fee receiver

This function allows for the modification of the fee receiver of a pool. Please note that this action is exclusively available to administrators.

Entrypoint

Handle

Input

InvariantAction::ChangeFeeReceiver(PoolKey, ActorId)

Input parameters

TypeDescription
PoolKeyThe pool key of the pool where the change is to be made.
ActorIdThe new fee receiver's address of the pool.

Errors

CodeDescription
NotAdminReverts the call when the caller is unauthorized user.

Fee tier

Add fee tier

This function enables the addition of a new fee tier, which users can subsequently utilize when creating pools. Please note that this action is restricted to administrators.

Entrypoint

Handle

Input

InvariantAction::AddFeeTier(FeeTier)

Input parameters

TypeDescription
FeeTierThe fee tier to be added.

Errors

CodeDescription
NotAdminFails if an unauthorized user attempts to create a fee tier.
InvalidTickSpacingFails if the tick spacing is invalid.
FeeTierAlreadyExistFails if the fee tier already exists.
InvalidFeeFails if fee is invalid.

Fee Tier exist

This function is used to verify the existence of a specified fee tier.

Entrypoint

State

Input

InvariantStateQuery::FeeTierExist(FeeTier)

Output

InvariantStateReply::FeeTierExist(bool)

Input parameters

TypeDescription
FeeTierThe key associated with the fee tier to be checked for existence.

Output parameters

TypeDescription
boolboolean indicating if the fee tier is added.

Get fee tiers

Retrieves available fee tiers.

Entrypoint

State

Input

InvariantStateQuery::GetFeeTiers

Output

InvariantStateReply::QueriedFeeTiers(Vec<FeeTier>)

Output parameters

TypeDescription
Vec<FeeTier>Vector containing all fee tiers added to specified pool

Remove fee tier

This function removes a fee tier based on the provided fee tier key. After removal, the fee tier will no longer be available for use in pool creation. It's important to note that existing pools with that fee tier will remain unaffected. This action is exclusively available to administrators.

Entrypoint

Handle

Input

InvariantAction::RemoveFeeTier(FeeTier)

Input parameters

TypeDescription
FeeTierThe key associated with the fee tier to be removed.

Errors

CodeDescription
NotAdminFails if an unauthorized user attempts to create a fee tier.
FeeTierNotFoundFails if fee tier does not exist.

Pools

Create pool

This function creates a pool based on a pair of tokens and the specified fee tier. The order of the tokens is irrelevant, and only one pool can exist with a specific combination of two tokens and a fee tier.

Entrypoint

Handle

Input

InvariantAction::CreatePool {
token_0: ActorId,
token_1: ActorId,
fee_tier: FeeTier,
init_sqrt_price: SqrtPrice,
init_tick: i32,
}

Input parameters

NameTypeDescription
token_0ActorIdAddress of the first GRC-20 token in the pair.
token_1ActorIdAddress of the second GRC-20 token in the pair.
fee_tierFeeTierThe fee tier to be applied.
init_sqrt_priceSqrtPriceThe square root of the price for the initial pool related to init_tick
init_ticki32The initial tick value for the pool.

Errors

CodeDescription
FeeTierNotFoundFails if the specified fee tier cannot be found.
TokensAreSameFails if the user attempts to create a pool for the same tokens.
PoolAlreadyExistFails if Pool with same tokens and fee tier already exist.
InvalidInitTickFails if the init tick is not divisible by the tick spacing.
InvalidInitSqrtPriceFails if the init sqrt price is not related to the init tick.

Get pool

This function retrieves a pool based on two tokens and the specified fee tier. It returns an error if the pool does not exist.

Entrypoint

State

Input

InvariantStateQuery::GetPool(ActorId, ActorId, FeeTier)

Output

InvariantStateReply::Pool(Pool)

Input parameters

TypeDescription
ActorIdAddress of the first token in the pair.
ActorIdAddress of the second token in the pair.
FeeTierThe fee tier of the pool you want to retrieve.

Output parameters

TypeDescription
PoolA struct containing pool data.

Errors

CodeDescription
PoolNotFoundFails if there is no pool associated with created key.
TokensAreSameFails if the user attempts to create a pool for the same tokens.

Get pools

Entrypoint

State

Input

InvariantStateQuery::GetPools

Output

InvariantStateReply::Pools(Vec<PoolKey>)

This function retrieves a listed pool keys.

Output parameters

TypeDescription
Vec<PoolKey>Vector with pool keys that indicates all pools listed.

Position

Create position

This function creates a position based on the provided parameters. The amount of tokens specified in liquidity delta will be deducted from the user's token balances. Position creation will fail if the user does not have enough tokens or has not approved enough tokens.

Entrypoint

Handle

Input

InvariantAction::CreatePosition {
pool_key: PoolKey,
lower_tick: i32,
upper_tick: i32,
liquidity_delta: Liquidity,
slippage_limit_lower: SqrtPrice,
slippage_limit_upper: SqrtPrice,
}

Output

    PositionCreatedReturn(Position)

Input parameters

NameTypeDescription
pool_keyPoolKeyThe pool key for which you want to create a position.
lower_ticki32The lower tick of your position.
upper_ticki32The upper tick of your position.
liquidity_deltaLiquidityThe liquidity you want to provide.
slippage_limit_lowerSqrtPriceThe lower square root of price fluctuation you are willing to accept.
slippage_limit_upperSqrtPriceThe upper square root of price fluctuation you are willing to accept.

Output parameters

TypeDescription
PositionThe position that was created.

Errors

CodeDescription
ZeroLiquidityFails if the user attempts to open a position with zero liquidity.
InvalidTickIndexOrTickSpacingFails if the user attempts to create a position with invalid tick indexes or tick spacing.
PriceLimitReachedFails if the price has reached the slippage limit.
TransferErrorFails if the allowance is insufficient or the user balance transfer fails.
PoolNotFoundFails if pool does not exist.
NotEnoughGasToExecuteOccurs when provided gas was too low to execute
NotEnoughGasToUpdateOccurs when provided gas turned out to insufficient to update after transfer

External Contracts

  • GRC-20

Transfer position

This function changes ownership of an existing position based on the position index in the user's position list. You can only change ownership of positions that you own; otherwise, it will return an error.

Entrypoint

Handle

Input

InvariantAction::TransferPosition {
index: u32,
receiver: ActorId,
}

Input parameters

NameTypeDescription
indexu32Index of the position in the user's position list.
receiverActorIdAddress of the user who will receive the position.

Remove position

This function removes a position from the user's position list and transfers the tokens used to create the position to the user's address.

Entrypoint

Handle

Input

InvariantAction::RemovePosition {
position_id: u32,
}

Output

InvariantEvent::PositionRemovedReturn(TokenAmount, TokenAmount)

Input parameters

NameTypeDescription
indexu32Index of the position in the user's position list.

Output parameters

TypeDescription
TokenAmountAmount of token X sent to the user's wallet address.
TokenAmountAmount of token Y sent to the user's wallet address.

Errors

CodeDescription
PositionNotFoundFails if Position cannot be found.
TransferErrorFails if an error occurs on the side of any of the withdrawn tokens
NotEnoughGasToExecuteOccurs when provided gas was too low to execute

External Contracts

  • GRC-20

Claim fee

Entrypoint

Handle

Input

InvariantAction::ClaimFee {
position_id: u32,
}

Output

InvariantEvent::ClaimFee(TokenAmount, TokenAmount)

This function allows the user to claim fees from an existing position. Tokens will be sent to the user's address.

Input parameters

NameTypeDescription
indexu32Index of the position in the user's position list.

Output parameters

TypeDescription
TokenAmountAmount of token X sent to the user's wallet address.
TokenAmountAmount of token Y sent to the user's wallet address.

Errors

CodeDescription
PositionNotFoundFails if Position cannot be found.
TransferErrorFails if an error occurs on the side of any of the withdrawn tokens
NotEnoughGasToExecuteOccurs when provided gas was too low to execute

External Contracts

  • GRC-20

Get position

This function returns an result that contains error if the position cannot be found or a position if it actually exists.

Entrypoint

State

Input

InvariantStateQuery::GetPosition(ActorId, u32)

Output

InvariantStateReply::Position(Position)

Input parameters

TypeDescription
ActorIdAn ActorId identifying the user who owns the position.
u32Index of the position in the user's position list.

Output parameters

TypeDescription
PositionFound position

Errors

CodeDescription
PositionNotFoundFails if Position cannot be found.

Get all positions

This function returns a list of positions owned by the caller. The list will be empty if you do not have any positions.

Entrypoint

State

Input

InvariantStateQuery::GetAllPositions(ActorId, u32)

Output

InvariantStateReply::Positions(Vec<Position>)

Input parameters

TypeDescription
ActorIdAn ActorId identifying the user who own the positions.

Output parameters

TypeDescription
Vec<Position>A list containing the user's positions.

Swap

Swap

This function executes a swap based on the provided parameters. It transfers tokens from the user's address to the contract's address and vice versa. The swap will fail if the user does not have enough tokens, has not approved enough tokens, or if there is insufficient liquidity.

Entrypoint

Handle

Input

InvariantAction::Swap {
pool_key: PoolKey,
x_to_y: bool,
amount: TokenAmount,
by_amount_in: bool,
sqrt_price_limit: SqrtPrice,
}

Output

InvariantEvent::SwapReturn(CalculateSwapResult)

Input parameters

NameTypeDescription
pool_keyPoolKeyPool key of the pool on which you wish to perform the swap.
x_to_yboolSpecifies the direction of the swap.
amountTokenAmountAmount of tokens you want to receive or give.
by_amount_inboolIndicates whether the entered amount represents the tokens you wish to receive or give.
sqrt_price_limitSqrtPriceIf the swap achieves this square root of the price, it will be canceled.

Output parameters

TypeDescription
CalculateSwapResultA struct containing the amount in and amount out with starting and target square root of price, taken fee, pool and vector of crossed ticks.

Errors

CodeDescription
AmountIsZeroFails if the user attempts to perform a swap with zero amounts.
PriceLimitReachedFails if the price has reached the specified price limit (or price associated with specified square root of price).
NoGainSwapFails if the user would receive zero tokens.
TransferErrorFails if the allowance is insufficient or the user balance transfer fails.
PoolNotFoundFails if pool does not exist.
NotEnoughGasToUpdateOccurs when provided gas was too low to perform a state update after calculation

External Contracts

  • GRC-20

Quote

This function performs a simulation of a swap based on the provided parameters and returns the simulation results. It does not involve any actual token transfers.

Entrypoints

Handle

Input

InvariantAction::Quote {
pool_key: PoolKey,
x_to_y: bool,
amount: TokenAmount,
by_amount_in: bool,
sqrt_price_limit: SqrtPrice,
}

Output

InvariantEvent::Quote(QuoteResult)
NameTypeDescription
pool_keyPoolKeyPool key of the pool on which you wish to perform the swap.
x_to_yboolSpecifies the direction of the swap.
amountTokenAmountAmount of tokens you want to receive or give.
by_amount_inboolIndicates whether the entered amount represents the tokens you wish to receive or give.
sqrt_price_limitSqrtPriceIf the swap achieves this square root of the price, it will be canceled.

Output parameters

TypeDescription
QuoteResultA struct containing amount of tokens received, amount of tokens given, square root of price after the simulated swap and list of ticks that has been crossed durning the simulation

Errors

CodeDescription
AmountIsZeroFails if the user attempts to perform a swap with zero amounts.
PriceLimitReachedFails if the price has reached the specified price limit (or price associated with specified square root of price).
NoGainSwapFails if the user would receive zero tokens.
PoolNotFoundFails if pool does not exist.

Quote Route

Entrypoints

Handle

Input

InvariantAction::QuoteRoute {
amount_in: TokenAmount,
swaps: Vec<SwapHop>,
}

Output

InvariantEvent::QuoteRoute(TokenAmount)

This function performs a simulation of multiple swaps based on the provided parameters and returns the simulation results. It does not involve any actual token transfers.

Input parameters

NameTypeDescription
amount_inTokenAmountAmount of tokens you want to swap.
swapsVec<SwapHop>A vector containing all parameters needed to identify separate swap steps.

Output parameters

TypeDescription
TokenAmountAmount of tokens received in the simulation.

Errors

CodeDescription
AmountIsZeroFails if the user attempts to perform a swap with zero amounts.
PriceLimitReachedFails if the price has reached the specified price limit (or price associated with specified square root of price).
NoGainSwapFails if the user would receive zero tokens.
PoolNotFoundFails if pool does not exist.

Tick

Get tick

Retrieves information about a tick at a specified index.

Entrypoint

State

Input

InvariantStateQuery::GetTick(PoolKey, i32)

Output

InvariantStateReply::Tick(Tick)

Input parameters

TypeDescription
PoolKeyA unique key that identifies the specified pool.
i32The tick index in the tickmap.

Output parameters

TypeDescription
TickA struct containing tick data.

Errors

CodeDescription
TickNotFoundFails if tick cannot be found.

Is tick initialized

Retrieves information about a tick at a specified index.

Entrypoint

State

Input

InvariantStateQuery::IsTickInitialized(PoolKey, i32)

Output

InvariantStateReply::IsTickInitialized(bool)

Input parameters

TypeDescription
PoolKeyA unique key that identifies the specified pool.
i32The tick index in the tickmap.

Output parameters

TypeDescription
boolboolean identifying if the tick is initialized in tickmap.