• 使用契约的链上限价订单


    我们开发了链上限价订单。 它基于一种称为契约的智能合约,只有在花费输出的交易满足特定条件时才可以花费输出。 为了演示其工作原理,我们实施了以比特币支付的 Ordinals 代币买卖限价订单,无需托管人。 它可以运行在任何比特币协议链上,例如Bitcoin SV和MVC

    限价订单

    限价单使买方或卖方(通常称为制造商)能够确定他们愿意在市场上买卖资产的特定价格。 随后,另一个交易者可以选择“接受”该报价并进行交易。 这一过程通常在托管交易所中得到促进,交易所暂时持有双方的资金,并采用内部结算机制来相应地分配资金。 然而,这种方法涉及将资金信任给第三方,从而使他们面临因系统黑客或内部盗窃而造成的潜在损失,其中第三方可能会消失或盗用资金。

    契约

    比特币契约 限制了 UTXO 的使用方式。 它是在 sCrypt 中使用 ScriptContext 实现的。

    例如,做市商可以下一个卖出订单,将 10 个 PEPE 代币锁定到契约合约中,允许任何购买者提取最多 10 个 PEPE 代币,只要他们向卖家支付,例如,他们移除的每个 PEPE 1000 聪。

    如果买方希望交易的金额低于 10 个 PEPE 限制(例如 7 个),他们可以选择为其余 3 个 PEPE 创建受相同契约约束的代币找零输出。 在这种特殊情况下,卖方被确定为做市商,买方在限价订单的框架内扮演接受者的角色。 该机制有利于部分履行限价订单的过程。

    该限价订单可以看作是 RUN 代币的 OrderLockOrdinals 的 OrdinalLock 的扩展,只能进行全额交易。

    如果订单未 100% 成交,合同还允许卖方取消订单并拿走剩余的 PEPE。

    实现

    我们使用 BSV-20 同质化代币 作为创建限价订单的示例,并用比特币进行交易。

    限价卖出订单

    一定数量的 BSV-20 代币被锁定在契约智能合约中。 买方可以从智能合约中获取部分或全部代币,前提是他在同一合约调用交易中向卖方支付要价。

    描述卖出限价订单的交易图

    买家可以通过在同一合约调用交易中将聪转移到买家的地址来兑换 BSV-20 代币。 这是在调用合约的“buy”公共方法时完成的。

    还有一种“cancel”方法,允许买家在订单未 100% 成交时取回资金。

    class BSV20SellLimitOrder extends BSV20V2 {
        // Total amount of tokens we're selling.
        @prop()
        readonly tokenAmt: bigint
    
        // Amount of tokens already sold.
        @prop(true)
        tokenAmtSold: bigint
    
        // The seller's public key.
        @prop()
        seller: PubKey
    
        // Asking price per BSV-20 token unit.
        @prop()
        pricePerUnit: bigint
    
        ...
    
        @method()
        public buy(amount: bigint, buyerAddr: Addr) {
            // Check token amount doesn't exceed total.
            assert(
                this.tokenAmtSold + amount < this.tokenAmt,
                'insufficient tokens left in the contract'
            )
    
            // Update cleared amount.
            this.tokenAmtSold += amount
    
            // Build transfer inscription.
            const transferInscription = BSV20V2.createTransferInsciption(
                this.id,
                amount
            )
            const transferInscriptionLen = len(transferInscription)
    
            // Fist output is the contract itself, holding the remaining tokens.
            // If no tokens are remaining, then terminate the contract
            const tokensRemaining = this.tokenAmt - this.tokenAmtSold
            let outputs = toByteString('')
            if (tokensRemaining > 0n) {
                outputs = this.buildStateOutput(1n)
            }
    
            // Ensure the sold tokens are being payed out to the buyer.
            outputs += BSV20V2.buildTransferOutput(
                pubKey2Addr(this.seller),
                this.id,
                amount
            )
    
            // Ensure the next output is paying the to the Bitcoin to the seller.
            const satsForSeller = this.pricePerUnit * amount
            outputs += Utils.buildPublicKeyHashOutput(
                            hash160(seller), satsForSeller)
    
            // Add change output.
            outputs += this.buildChangeOutput()
    
            // Check outputs.
            assert(hash256(outputs) == this.ctx.hashOutputs, 'hashOutputs mismatch')
        }
    
        @method()
        public cancel(buyerSig: Sig) {
            assert(this.checkSig(buyerSig, this.seller))
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    BSV20SellLimitOrder

    限价买入订单

    限价卖出订单非常相似。 只是这一次,智能合约中锁定了一定数量的比特币,而不是 BSV-20 代币。

    描述买入限价订单的交易图

    由于智能合约本身无法确认 BSV-20 代币的真实性,因此使用了预言机服务。 预言机通过签署其引用以及金额和代币的铭文来保证代币的有效性。 智能合约验证此签名。

    class BSV20BuyLimitOrder extends BSV20V2 {
        // Total amount of tokens we're buying.
        @prop()
        readonly tokenAmt: bigint
    
        // Amount of tokens already cleared.
        @prop(true)
        tokenAmtCleared: bigint
    
        // Public key of the oracle, that is used to verify the transfers
        // genesis.
        @prop()
        oraclePubKey: RabinPubKey
    
        // The buyer's public key.
        @prop()
        buyer: PubKey
    
        // Offered price per BSV-20 token unit.
        @prop()
        pricePerUnit: bigint
    
        ...
    
        @method()
        public sell(oracleMsg: ByteString, oracleSig: RabinSig, sellerAddr: Addr) {
            // Check oracle signature.
            assert(
                RabinVerifier.verifySig(oracleMsg, oracleSig, this.oraclePubKey),
                'oracle sig verify failed'
            )
    
            // Get token amount held by the UTXO from oracle message.
            const utxoTokenAmt = byteString2Int(slice(oracleMsg, 36n, 44n))
    
            // Check token amount doesn't exceed total.
            const remainingToClear = this.tokenAmt - this.tokenAmtCleared
            assert(
                utxoTokenAmt <= remainingToClear,
                'UTXO token amount exceeds total'
            )
    
            // Update cleared amount.
            this.tokenAmtCleared += utxoTokenAmt
    
            // Build transfer inscription.
            const transferInscription = BSV20V2.createTransferInsciption(
                this.id,
                utxoTokenAmt
            )
            const transferInscriptionLen = len(transferInscription)
    
            // Check that the ordinal UTXO contains the right inscription.
            assert(
                slice(oracleMsg, 44n, 44n + transferInscriptionLen) ==
                    transferInscription,
                'unexpected inscription from oracle'
            )
    
            // Ensure the tokens are being payed out to the buyer.
            let outputs = BSV20V2.buildTransferOutput(
                pubKey2Addr(this.buyer),
                this.id,
                this.tokenAmt
            )
    
            // Ensure the second output is paying the Bitcoin to the seller.
            const satsForSeller = this.pricePerUnit * utxoTokenAmt
            outputs += Utils.buildPublicKeyHashOutput(sellerAddr, satsForSeller)
    
            // If there's tokens left to be cleared, then propagate contract.
            if (this.tokenAmtCleared == this.tokenAmt) {
                outputs += this.buildStateOutput(
                    this.ctx.utxo.value - satsForSeller
                )
            }
    
            // Add change output.
            outputs += this.buildChangeOutput()
    
            // Check outputs.
            assert(hash256(outputs) == this.ctx.hashOutputs, 'hashOutputs mismatch')
        }
    
        @method()
        public cancel(buyerSig: Sig) {
            assert(this.checkSig(buyerSig, this.buyer))
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    BSV20BuyLimitOrder

  • 相关阅读:
    Objects.equals有坑
    【机器学习7】优化算法
    追求极致性能!Qwik 1.0版本发布
    Parade Series
    C# Socket通信从入门到精通(4)——多个异步TCP客户端C#代码实现
    Servlet知识点总结-DX的笔记
    RPC及Dubbo和ZooKeeper的安装
    Qt C++ TCP服务端响应多客户端通讯
    IntelliJ IDEA 配置启动SprintBoot项目
    企业架构LNMP学习笔记41
  • 原文地址:https://blog.csdn.net/freedomhero/article/details/134503953