ordinals / ord

👁‍🗨 Rare and exotic sats
https://ordinals.com
Creative Commons Zero v1.0 Universal
3.85k stars 1.38k forks source link

Proposal for Runes turbo = true features #3737

Closed summraznboi closed 5 months ago

summraznboi commented 6 months ago

Here I propose three new additions/extensions to the runes protocol, hope to get feedback and ideas!

All three of these ideas loosely extend from a mental model of each rune having these various "virtual" pools that related runes can be added or removed from, with open minting already being an example of this (Terms tags specify the total number of runes in the pool with amount * cap, and every Mint tag transfers amount runes from the mint pool to unallocated section).

Thus general pattern of the features below follow the pattern of tags used at etching to set up these pools with their specialized rules, and follow up tags is used to interact with the pools (whether withdrawing or depositing). To avoid any circular dependencies, tags that deposit runes into a pool only uses runes from input UTXOs directly, and not any runes potentially withdrawn from another pool. Also, in case of multiple pool deposit tags, tags are assessed in numerical ascending order.

Sorry for clumping all of these proposals together, but ideally all proposals below are released at the same time, since once any of these are released, future upgrade path becomes less trivial and more difficult (but I have an idea for that too, that will be in another issue later).

Swap

This sets up a simple Uniswap v2 constant product curve.

New Flag:

Swap,

New etching tags:

// 4 ints
// specifies the liquidity pair, so input the two runes by ID here
// encode this in rune ID delta format, so it ensures a consistent ordering
LiquidityPair,

// 1 int
// fee for each swap in basis points, defaults to 30 (equivalent to 0.3%)
FeeBasis,

// 1 int
// minimum liquidity on initial deposit that will never be withdrawn to cover rounding errors
MinimumLiquidity,

New operation tags:

// 2 ints
// Specifies the swap rune by ID to perform liquidity related operation with
LiquidityPool,

// 2 ints
// Deposit the pair of runes into swap pool, retrieve swap rune back
DepositLiquidity,

// 1 int
// Burn the swap rune to receive the pair of runes back
WithdrawLiquidity,

// 3 ints
// Specify an amount of one of the pair of runes to swap, as well as the min limit of the other rune expected
// If min limit cannot be achieved, the swap is failed and nothing happens instead
Swap,

Bonding Curve

This uses the Bancor price formula, where the price function exponent is specified in increments of $1 \over 128$ (this is so math to calculate using is consistent when using sqrt/multiplication/addition with IEEE754 floats). The price formula is $p(s) = C*s^e$.

Edict tag

// 4 ints
// Specify the reserve rune by ID, exponent, and constant factor
BondingCurve,

Operation tags

// 2 ints
// Specifies the curve rune by ID to perform curve related operation with
Curve,

// 2 ints
// reserve amount and min curve rune amount
// if min not achieved, nothing happens
BuyCurve,

// 2 ints
// curve rune amount and min reserve amount
// if min not achieved, nothing happens
SellCurve,

Lottery

This is super desired by @casey, so I had to add an idea here. We will actually add a new tag to Terms so that if set, a precondition is added for minting, which is requiring a certain amount of reserve runes deposited into the lotto pool for a successful mint. Then later once a winner is chosen from a PRNG using a future sequence of block hashes as seed, the winner can redeem the reward using the winning ticket.

Note we can keep tracking the winning ticket logic simple before redemption - winning ticket transfers to the first output that receives nonzero amount of the lotto runes, otherwise use pointer/default output policy.

Edict tag

// 4 ints, also require Terms flag
// Specifies the reserve rune ID, amount of reserve needed per mint,
// and number of consecutive blocks needed to hash together to generate random seed
Lottery,

Operation tag

// 2 ints
// Specifies the lotto rune ID, and if winning ticket detected, withdraw the winnings from pool
// noop otherwise
ClaimReward,
casey commented 5 months ago

These are very clever ideas! Unfortunately, miners would be able to extract significant MEV by front-running and sandwiching transactions, so this would negatively impact mining decentralization.

summraznboi commented 5 months ago

@casey I figured that you would mention MEV sandwich attacks for the first two, but can you take another look for lottery? I don’t think it has easy MEV since lotto winner is determined by blockhash which is already difficult enough to generate a valid one for a block, much less to manipulate to select a winner.

Also, I’ll think of potential ways to avoid MEV, and the top candidate is to order transactions through some transaction chain somehow.

casey commented 5 months ago

If the lottery winnings were significant, then miners might buy lottery tickets and attempt re-orgs on the block whose block hash selects the winner of the lotto. I don't want to rule out the possibility that there's a safe way to do this, but I can't think of one right now, unfortunately.