TL;DR
There are two groups of users: A) those who want more coins, B) those who want a higher price (less BCH liquidity). Together they can create a market where they work together toward their individual goals.
Introduction
With the advent of CashTokens, it is now possible to control and track tokens from smart contracts such as the Wrapped BCH contract by @dagurval .
Similar to a wBCH token, creating timelocked futures tokens would also be trivial by modifying the wrapOrUnwrap()
function of WrapBCH
into placeOrRedeem()
to control Bitcoin Cash Futures fungible tokens, locked until some blocktime.
A Futures issuer could send a supply of 21M fungible tokens each representing one coin locked until some block height in the future to the above contract and let anyone encumber coins by swapping them into the contract in return for a tradable tokenâredeemable at a later date.
A complicated token placement to market loop
It stands to reason, from an intuitive market perspective, that beyond the initial novelty, a Future should eventually sell at a discount to a normal liquid coinâit being less useful immediately. So the person who encumbered the coin will immediately have created a token that will probably then sell for less than what was input. The coin locker might always expect to lose money in the locking process itself.
From the buyerâs perspective however, theyâd essentially be buying BCH at a discount; thereâs financial incentive for a buyer to buy futures below the face value of the locked coin.
However, the locker that releases tokens from the FutureBCH
holding contract however would have a real asset at some price, so they could presumably receive some proceeds from the sale.
A lone locker, or the general practice locking coins to release the Futures, could create a liquid market where the price of a Future token started out below 100%, maybe 90% face value, to gradually increase reaching parity when the locktime was reached.
So the locker could loop some liquidity repeatedly in a geometric series where the sum of the amount locked would be the proportional to one minus the discount.
The amount that could be locked given a sacrificial amount at some market price would be a the sum of a geometric series:
So a locker with 1 coin, selling Futures at a rate of 0.9 BCH per futureBCH could cause a total of 10 coins to be locked.
A locker with 1 coin able to sell futures at a price of 0.95 BCH per futureBCH could cause 20 coins to be locked⌠etc.
At 0.99 BCH per futureBCH, one BCH could incentivize locking of 100 BCH. So although itâs literally throwing away coins on leverage, the effect on market liquidity could have an outsized impact if the discount was thin (if buyers were willing to buy futureBCH very near the face value of the underlying coin).
The net result of the extreme case is that the locker paid the buyer a coupon of 1 BCH to lock 100 BCH over the course of hundreds of trades through loops. If the net result is that someone will get paid a coupon for locking a large amount of coins, itâs possible to skip the looping of a geometric series, and the market and just create contracts holding come coupon funds where holders could harvest the coupon incentives at various rates.
So to place BCH and release Futures tokens, there is unnecessary complexity in the amount of âloopingâ involved, and the margins on the tokens would have to be very tight (+~98%) making trading the Futures on current dexes a non-starter because the fees (~0.3%) should be several hundred sats, or in the thousands when the futures near maturity or the holder will lose their incentive to trade such a narrowly priced asset.
A simplified approach; Skipping the dex and discount loop
If the party incentivizing the creation of the encumbered futures can come to terms with the fact theyâre essentially just paying people to save, then the whole rigmarole, the looping, as well as a necessary stop on the open market can be skipped, and Alice can just go take a coupon in one transaction with one tiny transaction fee:
Input | Output | ||
---|---|---|---|
FutureBCH(900000).function.placeOrRedeem(false) |
1 FutureBCH | => | 1 BCH |
aliceTemplate.unlockP2PKH() |
99.8M sats | => | 1 FutureBCH |
Coupon(900000).function.apply() |
200k sats | - |
One really simple and extremely flexible way to specify an arbitrary coupon down to the millionth of a percent would be to just have the FutureCoupon contract only spend a single output and restrict locking to whole coins.
So if someone wanted to offer a coupon of 100k sat for locking 100M sats, they could send a utxo (or stream of them) at the Coupon contract, and theyâd eventually get harvested as maturity date for the FutureContract approached.
For a CashScript 0.10.0-next generated Bitauth dubugging URL authenticaion template click HERE
In CashScript, using BIP65âs OP_CHECKLOCKTIMEVERIFY
for a fixed locktime in blocks.
pragma cashscript ^0.10.0;
// Future BCH fungible token vault
//
// Inputs: 00-covenant
// Outputs: 00-covenant
//
// [WIP] 2024-02-19
//
// enforcing token Category prevents coupons from being
// claimed on from random tokens sent to contract
//
contract FutureBCH(int locktime, bytes tokenCategory) {
function placeOrRedeem(bool isRedeem) {
// Flow
// 00 contract -> 00 contract
// 01 userPkh => 01 userPkh
// 02 coupons ^
// enforce BIP65 timelocks and the direction of the swap
if(isRedeem){
// tokens may be redeemed in any amount after the future has matured
require(tx.time >= locktime);
require(tx.inputs[1].tokenCategory == tokenCategory);
} else{
// otherwise, only whole coins may be "placed" or locked
// And the token id must match a pre-configured token
require(tx.inputs[0].tokenAmount == 100000000);
require(tx.inputs[0].tokenCategory == tokenCategory);
require(tx.inputs[1].value == 100000000);
require(tx.outputs[1].tokenCategory == tokenCategory);
}
// Enforce that this contract lives on
require(
tx.outputs[this.activeInputIndex].lockingBytecode
==
tx.inputs[this.activeInputIndex].lockingBytecode,
"locking bytecode index mismatch"
);
require(
tx.inputs[this.activeInputIndex].tokenAmount +
tx.inputs[this.activeInputIndex].value
==
tx.outputs[this.activeInputIndex].tokenAmount +
tx.outputs[this.activeInputIndex].value,
"summation mismatch"
);
}
}
A coupon contract isnât necessarily specific to being used for futures. To restrict spending of a utxo toward a single contract seems straight-forward:
pragma cashscript ^0.10.0;
// Restrict output of any utxo to a preconfigured address
contract Coupon(
// Locking bytecode the coupon will be applied to
bytes destinationLockingBytecode
){
function apply() {
// Require all utxos be spent atomically
require(tx.inputs.length == 1);
require(tx.outputs.length == 1);
// assure at the entire amount minus a transaction fee
// goes to the intended output
int appliedAmount = tx.inputs[0].value - 1500;
require(tx.outputs[0].value >= appliedAmount);
// Check that the first output
// sends to the intended recipient.
require(
tx.outputs[0].lockingBytecode
== destinationLockingBytecode
);
}
}
Given the bitcoin reward schedule, it might make sense to align contract expiration with intervals pertaining to block rewards. i.e. 210,000 cycle multi-year periods, 1000 block increments for weeklies, etc.
Market Example
Bob sends a small output as a coupon for Alice to place coins in a timelock. The coupon acts as a standing irrevocable bid in an open ended auction terminating at contract expiration. Once Alice places her coin in the vault, it may only be withdrawn after expiration for a corresponding amount of tokens. However, if Alice wants liquidity in the meantime, she may then sell her dated futures tokens on the open market.
Bob may send 1000 sats toward a coupon to lock 100M sats for 1000 blocks (1 week). This is not incentive for Alice to open a wallet or move coins, so the coupon is left unused.
Bob, frustrated and impatient, might dispense an array of UTXOs to the coupon contract in increments of 10k (20k, 30k, ⌠200k) until Alice decides that 0.2M sats is sufficient incentive to place 100M sats for one week. The process of locking is easy enough, she takes the 190k sat coupon too.
BANG! Price discovery. Alice has decided with the help of Bob, that the prevailing spot rate of interest on Bitcoin Cash futures will be 0.19% on the week, or an annualized rate of 10.374%.
The following day, with 900 blocks until expiration, the 180k and 170k coupons are exceed the 0.19% rate, and Charlie locks two coins taking those coupons.
With this simple standing auction, Alice and Charlie locked a total of 400M sats for a nominal interest rate of 10% APR, and Bob has cause 400M coins to become locked until payday for the low low price of 2.1M sats.
It is conceivable, if the week continues, that new buyers may collect the smaller coupons closer to expiration and Bob may cause 21 BCH to be locked with his 2.1M sats by the end of the week. If not, unclaimed coupons may be collected after the contract lock time has been exceeded.
This is an adaptation of some thoughts of how to do futures (w/o tokens)⌠@emergent_reasons.
Anyway, Iâve tried to go through the potential market dynamics and game theory. I think the quickest way to deep liquidity with these assets is to skip the DEX and load the incentive explicitly as a coupon.