Decentralized grid trading on Ergo

There are some issues with contracts above, current version with fixes done (for ERG/SigUSD pair):

{
    // decentralized grid order contract for token/ERG trading, with ERG accumulation

    val tokenId = fromBase64("A/ryyzKfLpDW0jtY2Ru7bARqoUMmHMIfUvvigkv8vwQ=") // SigUSD

    // script of order owner
    val ownerScript = SELF.R4[SigmaProp].get

    // token price, in nanoErg per token (so nanoErg per USD cent)
    val tokenPrice = SELF.R5[Long].get

    //our order side, TRUE == BUY, false == SELL
    //BUY means we are buying tokens with ERGs, SELL means we sell tokens for ERGs
    val side = SELF.R6[Boolean].get

    //how many tokens we are buying or selling
    val orderSize = SELF.R7[Long].get

    // new price targets for buy and sell actions, respectively
    val targets = SELF.R8[Coll[Byte]].get

    val outIndex = 1 // TODO: check composability

    val recreatedBox = OUTPUTS(outIndex)

    val newPrice = if(side) {
      tokenPrice * targets(0) / 100 // if our order is buy, we are going to sell in a new order, 
    } else {
      tokenPrice * targets(1) / 100 // if our order is sell, we rebuy @ lower price
    }

    // check conditions not related to trading here
    val orderRecreated = (
        recreatedBox.propositionBytes == SELF.propositionBytes &&
        recreatedBox.R4[SigmaProp].get == SELF.R4[SigmaProp].get &&
        recreatedBox.R5[Long].get == newPrice &&
        recreatedBox.R6[Boolean].get != side  && //side is flipped
        recreatedBox.R7[Long].get == orderSize  &&
        recreatedBox.R8[Coll[Byte]].get == SELF.R8[Coll[Byte]].get  &&
        // protection from spending multiple orders with the same output
        recreatedBox.R9[Coll[Byte]].get == SELF.id
    )

    val nanoErgsDifference = if(side) {
      // we are buying token - should be more ERG in our order box than in child
      SELF.value - recreatedBox.value
    } else {
      // we are selling token - so should be more in child order than ours
      recreatedBox.value - SELF.value
    }

    val tokensCheck = if(!side) {
      // if we're selling tokens, we sell all of them
      recreatedBox.tokens.size == 0
    } else {
      // check ID and amount of token we're buying
      recreatedBox.tokens(0)._1 == tokenId && recreatedBox.tokens(0)._2 == orderSize
    }

    val exchangeOK = if(side) {
      nanoErgsDifference <= orderSize * tokenPrice
    } else {
      nanoErgsDifference >= orderSize * tokenPrice
    }


    // no fee condition here

    sigmaProp(
        ownerScript ||
        (
            orderRecreated && exchangeOK && (nanoErgsDifference > 0) && tokensCheck
        )
    )
}

Its P2S address:

3STRfQkJvGgMQ9JrSpvAwMPABQrRidwYCCPadHtzHcrpyUJBeA6o6Ua3fb7xGr5z4Cxhp56oqERn8H97ewp1PPemqDEkqM3MQ9pXXhjHnxJEayFQPdobNB829duPZeRj9zDRKTHQ97tEXFgZwCcveDXMQYdt4w8rYm7SVURCUK2PimkM5PgvaRT7DdxjVefGGzcHRXfSyQkUSWrmJb5mUuyPz4LGSofRaksNZG7yKMtrBqDniG1KfE5cFZhMEFRnUgSBnZqn6vxfzXtJEFdhdJPemg3XKKDAoAiTrcsWgbTzuoqDsu3MCm54fy4adVFJG9E6ENujSrW1UgYt1c8uBbJhqMZDHPaBRsECWd4cNVb6Z92T6S5zgvLfwLs2rFvHmfTA3NsW5

And thus custom tracking rule for grid orders:

{
  "scanName": "Grid orders",
  "walletInteraction": "off",
  "removeOffchain": false,
  "trackingRule": {
    "predicate": "equals",
    "value": "0e9b0210090402040005c801040205c8010500040004000e2003faf2cb329f2e90d6d23b58d91bbb6c046aa143261cc21f52fbe2824bfcbf04d807d601e4c6a70408d602b2a5730000d603e4c6a70601d604e4c6a7080ed605e4c6a70505d606e4c6a70705d60795720399c1a7c1720299c17202c1a7eb027201d1ededededededededed93c27202c2a793e4c672020408720193e4c6720205059572039d9c72057eb272047301000573029d9c72057eb2720473030005730494e4c672020601720393e4c672020705720693e4c67202080e720493e4c67202090ec5a79572039072079c720672059272079c72067205917207730595ef720393b1db630872027306d801d608b2db63087202730700ed938c7208017308938c7208027206"
  }
}

So I made offchain part which is working with the node just, and was able to do trades against Spectrum’s AMM LP : Ergo Explorer

I will open-source offchain part at some point, at the moment it is dirty and UI is creepy )

grid

Decentralized grid orders can be seen as a first example of smart orders, so orders which can requirements additional to just fulfillment (in this case, an order is requiring for an order in opposite direction to be created).

I am thinking to play a bit more and then ask some whales from around to put money into a grid, such as the grid will assume price growth with time (for SigUSD bought, selling price would be e.g. +6%, after selling price to re-buy will be -4%). Accumulated ERG profits will be shared with a treasury for community-based marketing machine, thus whales and community based marketing group will work towards the same goal, with transparency and agreement enforcement (most critical parts of it) to be done on-chain.

7 Likes