Skip to content

Instantly share code, notes, and snippets.

@shesek
Created February 16, 2022 14:14
Show Gist options
  • Save shesek/be910619b247ce5e1aedd84e9ba9db42 to your computer and use it in GitHub Desktop.
Save shesek/be910619b247ce5e1aedd84e9ba9db42 to your computer and use it in GitHub Desktop.
// Witness stack
// Extra params for call type
// Bid - 0x00
//<0xbc86756ef30eb2d1457f3ddb7d627ceafbcc6be4e61d8e1e15d197900aea9dcc> $N_bidder_pk
// Redeem - 0x01
<0x1111> $redeem_sig
// Call - 0x00 to bid, 0x01 to redeem after a timeout
<0x01> $call
// State
// Current highest bidder public key (initially FALSE)
OP_FALSE $S_bidder_pk
//<0x1efc611e1e6feffd661894690e1354ac6269215bd370e9f8f73ed80ea1449705> $S_bidder_pk
// Constants
// Contract own tapscript for recursive enforcment (excluding state and this constant -- only ops from this point onwards, starting at the push for the next constant)
<0x201dae61a4a8f841952be3a511502d4f56e889ffa0685aa0098773ea2d4309f62420eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee20cf3567f81e19e3e21cd29c18e6f670b5e9a1c63ef9e2c2fada68e1a4a7e584c020e997e1eb1a8d69d04cbabc59a0c71670016ee4205efb6b30407835661da168b602a005cd008851b275cdcb04FFFFFFFD88577a64757c75cdc86900ce6988cdc96900cf6988517a51ce698851d1518888527a76647567cdc701008804000000008851c70100880401000000888851cf6951c969de6952ce6951c8698852cf6951c9698852d151888868527a8201208801207c7e527a7682014d7c7e7c7e7c7e7e67b275567a567a766475527a686d68> $own_script
// A point with unknown discrete logarithm (for script-path-only construction)
<0x1dae61a4a8f841952be3a511502d4f56e889ffa0685aa0098773ea2d4309f624> $H
// tL-BTC asset id
<0x499a818545f6bae39fc03b637f2a4e1e64e590cac1bc3a6f6d71aa4443654c14> $LBTC
// Covenant for the BTC held by the contract (script-path-only p2tr pubkey)
<0xcb395437dc2748292e78987a801c89132a24cb5c0c19380ab71a9a00e5f8a3ac> $btc_covenant
// Minimum price
<0x0100000000000000> $min_price
// Seller's public key
<0xcf3567f81e19e3e21cd29c18e6f670b5e9a1c63ef9e2c2fada68e1a4a7e584c0> $seller_pk
// Timeout for redeeming the auction
<1440> $timeout
// BTC covenant script: 7464cdc70100887500c7010088040000000088876702<timeout 2 bytes>b27520<seller pk 32 bytes>ac68
// OP_DEPTH OP_NOTIF
// OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTOUTPOINT <0x00> OP_EQUALVERIFY OP_DROP
// <0> OP_INSPECTINPUTOUTPOINT <0x00> OP_EQUALVERIFY <0x00000000> OP_EQUALVERIFY
// OP_EQUAL
// OP_ELSE
// <timeout 2 bytes> OP_CHECKSEQUENCEVERIFY OP_DROP
// <seller pk 32 bytes> OP_CHECKSIG
// OP_ENDIF
// Preliminary checks
// Must be spent at index 0
OP_PUSHCURRENTINPUTINDEX <0> OP_EQUALVERIFY
// Prevent unconfirmed chain
<1> OP_CHECKSEQUENCEVERIFY OP_DROP
// Require RBF to be enabled
OP_PUSHCURRENTINPUTINDEX
OP_INSPECTINPUTSEQUENCE
<0xFFFFFFFD>
OP_EQUALVERIFY
// Main body
<8> OP_ROLL // bring call type to top
// Bid (call 0x00)
<0x00> OP_EQUAL OP_IF
// Drop the timeout and the seller pk (only needed for the redeem branch)
OP_2DROP
// Verify the auction asset is reconstructed at output #0
// Same asset id
OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTASSET OP_VERIFY
<0> OP_INSPECTOUTPUTASSET OP_VERIFY
OP_EQUALVERIFY
// Same amount
OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE OP_VERIFY
<0> OP_INSPECTOUTPUTVALUE OP_VERIFY
OP_EQUALVERIFY
// The SPK is checked below
// Verify payment output at output #1
// Pays to the BTC covenant script
// (stipulating that must be spent alongside this covenant, or after a timeout with the seller's signature)
OP_SWAP
<1> OP_INSPECTOUTPUTSCRIPTPUBKEY <1> OP_EQUALVERIFY
OP_EQUALVERIFY
// Is L-BTC
OP_SWAP
<1> OP_INSPECTOUTPUTASSET OP_VERIFY
OP_EQUALVERIFY
// The amount is checked below
// Bring current highest bidder to top (might be FALSE if there isn't one)
<3> OP_ROLL
// First bidder
OP_SIZE <0> OP_EQUAL OP_IF OP_DROP
// Verify it pays more than the minimum bid amount
<1> OP_INSPECTOUTPUTVALUE OP_VERIFY
OP_SWAP
OP_GREATERTHAN64 OP_VERIFY
// Outbidders
OP_ELSE
OP_NIP // Drop the minimum bid amount (only needed for first bidder)
// The BTC output with the previous bidder's bid must be spent alongside the auction item asset covenant
// Input #0 is this input (the auction item asset), input #1 is the previous bid BTC
OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTOUTPOINT <0x00> OP_EQUALVERIFY <0x00000000> OP_EQUALVERIFY
<1> OP_INSPECTINPUTOUTPOINT <0x00> OP_EQUALVERIFY <0x01000000> OP_EQUALVERIFY
OP_EQUALVERIFY
// Check payment amount in output #1 pays more than the previous bid
<1> OP_INSPECTOUTPUTVALUE OP_VERIFY
<1> OP_INSPECTINPUTVALUE OP_VERIFY
OP_GREATERTHAN64 OP_VERIFY
// Already checked to be L-BTC and to the covenant's spk above
// Verify refund to previous bidder at output #2
// Is L-BTC
<2> OP_INSPECTOUTPUTASSET OP_VERIFY
<1> OP_INSPECTINPUTASSET OP_VERIFY
OP_EQUALVERIFY
// Returns the input amount in full
<2> OP_INSPECTOUTPUTVALUE OP_VERIFY
<1> OP_INSPECTINPUTVALUE OP_VERIFY
OP_EQUALVERIFY
// Pays to the previous bidder pk (pops S_bidder_pk off the stack)
<2> OP_INSPECTOUTPUTSCRIPTPUBKEY <1> OP_EQUALVERIFY
OP_EQUALVERIFY
OP_ENDIF
// Bring new highest bidder pk to top and verify its size
<2> OP_ROLL
OP_SIZE <32> OP_EQUALVERIFY
// Verify the auction asset remains under the covenant at output #0 with the updated state
// Construct new state (push for new bidder pk)
<0x20> OP_SWAP OP_CAT $N_state
// Construct new tapscript (state + push(own_script) + literal own_script)
<2> OP_ROLL
OP_DUP
// PUSH for own_script (no state)
OP_SIZE
<0x4d> // PUSH with two bytes for the size (0x4c for shorter scripts with a size of 1 byte)
OP_SWAP
OP_CAT
OP_SWAP
OP_CAT
// Append literal <own script> code (actual opcodes)
OP_SWAP OP_CAT
// Prepend state blog
OP_CAT $N_script
// TODO build tweak key and verify
OP_2DROP OP_TRUE
// Redeem after timeout (call 0x01)
OP_ELSE
OP_CHECKSEQUENCEVERIFY OP_DROP
// Drop unused constants (only needed for the bid branch)
OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP
<2> OP_ROLL // bring signature
// Release asset to the highest bidder pk, if there is one (may be OP_FALSE)
<2> OP_ROLL // bring S_bidder_key to top
// Otherwise, release back to the seller pk
OP_SIZE <0> OP_EQUAL OP_IF
OP_SWAP <2> OP_ROLL // bring seller_pk to top
OP_ENDIF
OP_2DROP OP_TRUE // XXX OP_CHECKSIG
OP_NIP // drop unused key
OP_ENDIF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment