Sovryn supports limit orders for both spot and margin trading. When a limit order is placed on a centralized platform, the platform has complete control over how the limit order is filled. Users must trust the platform to fill the order in good faith. By contrast, Sovryn’s limit order function is decentralized and trustless. This property rules out the use of a single platform-controlled agent to fill limit orders. Instead, many independent processes compete to fill a limit order. All of these entities must follow the parameters set by the users, and all are incentivized by a fee-sharing mechanism.
Github repository for the Limit Orders:
https://github.com/DistributedCollective/LimitOrder
Limit orders
A limit order is a request to trade an asset at a pre-specified price. Whereas a market order executes immediately after an order is placed, a limit order will not execute unless the asset reaches the price set by the user. If the asset reaches this price, the order may be partially or completely filled depending on market conditions. Limit orders attempt to anticipate future prices, usually within a limited time frame. Therefore, the user can set an expiration period so that the order will either expire or be filled in the specific amount of time the user expects the price to reach the limit. Users may also place orders with no expiration and simply cancel them as needed.
Sovryn’s limit order function offers capital efficiency. On centralized exchanges, users are restricted in the number of limit orders that can be submitted with the same capital. Centralized exchanges must collateralize these orders, so allowing users to set many limit orders with the same capital involves increasing risk. The Sovryn protocol does not have to bear any risk because it does not custody the collateral. If a limit order is filled and insufficient collateral is available for pending limit orders, they simply fail to execute. Since many limit orders can be entered based on the same collateral, users can more efficiently use their funds to capitalize on movements in the price.
In an AMM (automated market maker) transaction, gas fees, slippage, and price impact can make up a significant share of the transaction cost. Because these costs are calculated up front as part of the overall price, a user placing a limit order on knows in advance what the overall cost of the trade will be.
In limit order transactions, users do not pay the cost of gas directly. Instead, filler bots pay the gas fee on behalf of users. These filler bots will only execute the trade if the price including gas and fees is less than the limit order price specified by the user. Instead of paying gas to submit the limit order, users execute a gasless signing operation via a web3 wallet. When users sign a transaction, they agree to allow the filler bots to fill the order when the order conditions are met.
The price specified for a limit order includes all the fees. If a user signs a transaction to sell a given token for a specified price, then the filler bots will fill that order only if the price plus slippage and fees is at least as good as the price specified by the user. If selling (or buying) the token affects the price to such a degree that it moves out of the limit set by the user, then the filler bot may only fill the order partially.
When the user creates a limit order for a purchase or sale on Sovryn, the order is added to an orderbook on a smart contract on testnet. Filler bots constantly observe the orderbook contract as well as the prices on the AMM. If a match occurs they relay the signed transaction. These bots are not run by or controlled by the Sovryn protocol. They can implement the order fill using any method they choose, as long as the transaction fulfills the requirements of the limit order.
Filler bots are rewarded for monitoring events and filling orders because they collect a fee any time they fill an order. These filler bots have wallet addresses with private keys and public keys just like human users and automated protocols do. Public key cryptography allows the bot, the user, and the protocol to communicate and verify transactions. Using this method, users verifiably pre-sign the order to be fulfilled when the limit order conditions are met. This is done in such a way that the bot can only fill an order for a genuine limit order executed and signed by a user wallet. To execute the trade itself, the filler bot calls the smart contract for the pair requested by the user if/when the price reaches the value set in the limit order. The smart contract in turn fills the order by sending funds to the AMM or loan token contract first. In the process, the smart contract sends the limit order fee to the filler bot as profit.
Limit Orders will be executed at the closest possible price to the Limit Price that the user defines when placing the order, whilst making sure that the user receives the minimum number of tokens/position size that was confirmed at order placement. Each trading type uses a slightly different method for calculating the amount of tokens that the user should receive, see below or on the Limit Order repository for more details.
relayerFee
= max(minSwapOrderTxFee
, 0.2% of amountIn
)minReturn
= (amountIn
- relayerFee
) * limitPrice
A Spot limit order will be executed when: the number of tokens to be received at the time of execution (as per above calculation) is greater or equal to the amount that the user confirmed when placing the order (the “minimum tokens to receive” amount). Since the amount of tokens to be received is affected by the relayer fee and slippage, in certain cases this can mean the actual executed price may be worse than the limit price the user entered at order placement, but it is ensured that the user receives at least the expected amount of tokens, after paying the relayer fee.
totalRelayerFee
= max(minMarginOrderFee
, 0.2% of total(convertToCollateral(loanTokenSent
), collateralTokenSent
) )relayerFeeInCollateral
= min(totalRelayerFee
, collateralTokenSent
)relayerFeeInLoanToken
= convertToLoanToken(totalRelayerFee
- relayerFeeInCollateral
)principal
= loanToken.getEstimatedMarginDetails( leverageAmount
, loanTokenSent
- relayerFeeInLoanToken
, collateralTokenSent
- relayerFeeInCollateral
, collateralTokenAddress
);positionSize
= loanTokenSent
+ principal
minEntryPrice
= convertToCollateral(positionSize
) / positionSize
A Margin limit order will be executed when: the amount of tokens to be traded at the time of execution (as per above calculation) is greater or equal to the amount that the user confirmed when placing the order (number of tokens equal to the positionSize
). Since the amount of tokens to be received is determined by slippage and the fee calculated in the loanToken
& collateralToken
for the trade pair, in certain cases this can mean the actual fill price may be worse than the limit price the user entered at order placement, but it is ensured that the user receives enough tokens to open a position of the desired size, after paying the relayer fee.