Skip to content

Ordinal Lock

Permissionless ordinal purchase with seller-signed cancellation.

txt
# A listed ordinal can be purchased permissionlessly if outputs pay the item and price correctly.
# The seller can also cancel the listing with a matching signature.
Contract OrdinalLock:

    Struct Script:
        SuffixData: string
        PartialHash: string
        Size: number

    Struct Output:
        Value: number
        LockingScript: Script

    Struct CurrentTX:
        Outputs: Output[3]

    # `path == 1` purchases the ordinal; any other path cancels with the seller signature.
    def main(dest: hex, sig: hex, pubkey: hex, ctx: CurrentTX, path: number):
        if path == 1:
            Delete(sig)
            Delete(pubkey)

            # Output 0 sends the one-satoshi ordinal to the buyer-supplied address hash.
            out0_suffix = ctx.Outputs[0].LockingScript.SuffixData.Clone()
            { out0_prefix, out0_suffix } = Split(out0_suffix, 3)
            EqualVerify(out0_prefix, 0x76a914)
            { out0_pkh, out0_tail } = Split(out0_suffix, 20)
            EqualVerify(out0_pkh, dest)
            EqualVerify(out0_tail, 0x88ac)
            out0_value = BinToNum(ctx.Outputs[0].Value.Clone())
            NumEqualVerify(out0_value, 1)

            # Output 1 pays the configured price to the seller address hash.
            out1_suffix = ctx.Outputs[1].LockingScript.SuffixData.Clone()
            { out1_prefix, out1_suffix } = Split(out1_suffix, 3)
            EqualVerify(out1_prefix, 0x76a914)
            { out1_pkh, out1_tail } = Split(out1_suffix, 20)
            EqualVerify(out1_pkh, self.seller)
            EqualVerify(out1_tail, 0x88ac)
            out1_value = BinToNum(ctx.Outputs[1].Value.Clone())
            NumEqualVerify(out1_value, self.price)

            # Bind the two required outputs and optional change to the current transaction.
            outputs_data = Push(0)
            SetAlt(outputs_data)
            for i in Range(2, -1, -1):
                size = ctx.Outputs[i].LockingScript.Size.Clone()
                if size != 0:
                    output_script = PartialHash(ctx.Outputs[i].LockingScript.SuffixData, ctx.Outputs[i].LockingScript.PartialHash, ctx.Outputs[i].LockingScript.Size)
                    output = Cat(ctx.Outputs[i].Value, output_script)
                    SetMain(outputs_data)
                    outputs_data = Cat(output, outputs_data)
                    SetAlt(outputs_data)
                    Keep(outputs_data)
                else:
                    Delete(ctx.Outputs[i].LockingScript.Size)
                    Delete(ctx.Outputs[i].LockingScript.PartialHash)
                    Delete(ctx.Outputs[i].LockingScript.SuffixData)
                    Delete(ctx.Outputs[i].Value)
            SetMain(outputs_data)
            outputs_data = Sha256(outputs_data)
            EqualVerify(outputs_data, BVM.outputsHash)
        else:
            # Cancel does not constrain outputs; ownership is proven by the seller key.
            Delete(dest)
            Delete(ctx)
            EqualVerify(Hash160(pubkey.Clone()), self.seller)
            CheckSigVerify(pubkey, sig)