diff --git a/README.md b/README.md index 89e2aa1..25a5983 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ over the multi-asset order book to obtain a list of matches. The matches are the translated into transactions that will be signed and submitted by the bot. Due to the open and decentralized design of the protocol, anybody can run a Smart Order -Router instance and collect a share of the fees, thus running a Smart Order Router instance -is not only contributiung to the further decentralization of the protocol, but it is also +Router instance and collect the arbitrage opportunities, thus running a Smart Order Router instance +is not only contributing to the further decentralization of the protocol, but it is also incentivized financially. ## Crash Course: GeniusYield DEX Orders and the Smart Order Routers @@ -128,6 +128,13 @@ If we want our earnings to be in `tokenA` then the commodity must be `tokenB`. So we can buy from the sell order, `20 tokenB` using `8 tokenA`, then using these `20 tokenB` we can get `10 tokenA` from the buy order, earning `2 tokenA`. +> [!IMPORTANT] +> +> There is a check in the end which does the following before submitting any transaction: +> +> * In case "currency" is set to ADA for all `scanTokens` then this check guarantees that bot doesn't lose any funds by submitting the built transaction. +> * For other case, since arbitrage isn't guaranteed to be in ADA but as transaction fees must be paid in ADA, this check guarantees that bot doesn't lose any non-ADA token and doesn't lose any ADA besides transaction fees. + ## Building and running the Smart Order Router > [!NOTE] @@ -182,7 +189,9 @@ docker run -it \ And the following commands can be used to start a Kupo backed instance, if you want to use an existing Kupo instance: - > **ⓘ How to run Kupo efficiently?** + > [!TIP] + > + > **How to run Kupo efficiently?** > > Firstly, Kupo requires a node running, note that node itself maintains efficient access to information such as current protocol parameters, current set of pool ids, etc. but it doesn't efficiently provide us with UTxOs when say queried by a particular address. Kupo helps in covering this gap and gives us efficient lookup tables to query for UTxOs. For our use case, we are only interested in our own bot's UTxOs, order UTxOs and the required reference scripts / reference inputs. So we'll run Kupo to keep track of only those UTxOs, note that if we instead run Kupo by matching against star (`*`) pattern, then as Kupo does many disk writes, we would quickly burn out our SSDs TBW limit. > @@ -414,7 +423,7 @@ Once we compiled and configured the order bot, you can execute the SOR using the The SOR is equipped with a test suite that employs QuickCheck to perform property-based testing. By implementing certain properties, we are able to verify various important aspects of the strategies, -like for example, given a matching between sell and buy orders there is always a [positive earning](./geniusyield-orderbot/test/Tests/Prop/Strategies.hs#L167-L177). +like for example, given a matching between sell and buy orders there is always a non-negative earning. Among others that can be found on [Tests.Prop.Strategies](./geniusyield-orderbot/test/Tests/Prop/Strategies.hs) module. diff --git a/geniusyield-orderbot-framework/src/GeniusYield/OrderBot.hs b/geniusyield-orderbot-framework/src/GeniusYield/OrderBot.hs index af8be63..c10c1a7 100644 --- a/geniusyield-orderbot-framework/src/GeniusYield/OrderBot.hs +++ b/geniusyield-orderbot-framework/src/GeniusYield/OrderBot.hs @@ -306,7 +306,7 @@ notLosingTokensCheck netId providers botAddr oapFilter (txBody, matchesToExecute utxosLovelaceAndFilteredValueAtAddr $ txBodyUTxOs txBody fees = txBodyFee txBody - lovelaceCheck = inputLovelace - outputLovelace <= fees + lovelaceCheck = if all currencyIsLovelace oapFilter then outputLovelace >= inputLovelace else inputLovelace - outputLovelace <= fees filteredACCheck = all (\ac -> valueAssetClass filteredACInput ac @@ -351,6 +351,9 @@ notLosingTokensCheck netId providers botAddr oapFilter (txBody, matchesToExecute second (valueFromList . filter (botAssetFilter . fst) . valueToList) $ valueSplitAda $ utxosValueAtAddr utxos + currencyIsLovelace :: OrderAssetPair -> Bool + currencyIsLovelace oap = currencyAsset oap == GYLovelace + ------------------------------------------------------------------------------- -- Helpers -------------------------------------------------------------------------------