将 Ordinals 与比特币智能合约集成:第 4 部分

news2025/5/25 23:10:23

控制 BSV-20 代币的分配

在上一篇文章中,我们展示了智能合约可以在铸造后控制 BSV-20 代币的转移。 今天,我们演示如何控制此类代币的分发/发行。

无Tick模式

BSV-20 在 V2 中引入了无Tick模式,并采用了与 V1 不同的方法。

部署 (Deploy)

要部署和铸造供应量为 21000000 的代币,请写入以下 JSON(ContentType:application/bsv-20):


{ 
  "p": "bsv-20",
  "op": "deploy+mint",
  "amt": "21000000",
  "sym": "sCrypt",
  "dec": "10"
}

请注意,与 V1 不同,没有指定的 tick 字段(因此无 tick)。

sym 字段仅代表代币名称,不用于建立代币的索引。

发行 (Issue)

要发行上述 10000 个代币,您可以使用以下 JSON 创建转移铭文:

{ 
  "p": "bsv-20",
  "op": "transfer",
  "id": "3b313338fa0555aebeaf91d8db1ffebd74773c67c8ad5181ff3d3f51e21e0000_1"
  "amt": "10000",
}

代币不是通过 tick 来标识,而是通过 id 字段来标识,该字段由交易 ID 和部署代币的输出索引组成,格式为 _。

此外,第一个发行交易必须从部署交易中支出,因为整个供应量是立即铸造的,而铸造交易不会从中支出,并且它们在 V1 中是分开的。 这意味着代币的每笔交易都可以追溯到该代币的创世部署,并且每笔交易都位于植根于创世交易的 DAG(有向无环图)中。 这使得 BSV-20 索引器能够更有效地扩展,因为它不必扫描整个区块链并排序铸币交易,以强制“first is first”铸币。

有关 BSV-20 代币 V2 工作原理的更多详细信息,请阅读官方文档。

公平发布

与 ERC-20 代币相比,BSV-20 V1 代币的一个显着特点是公平发行。 具体来说,一旦有人在 BSV-20 上部署代币交易,每个人都有相同的机会领取代币。 发行人不能免费预留一部分,即没有预挖。

如果在 V2 无代码模式下部署时一次性铸造出总供应量,是否可以保持公平发布?

答案是肯定的。 我们在部署时没有将整个供应锁定在标准发行人地址(P2PKH 脚本)中,而是将其锁定在智能合约中。 任何人都可以调用智能合约,并且可以在其中执行任何分配策略。
在这里插入图片描述
在上图中,每个方框代表一个代币 UTXO,堆叠的 UTXO 位于同一笔交易中。 第二笔交易花费了第一笔部署交易的 UTXO(如第一个箭头所示),并创建了两个 UTXO:

  • 创世时相同合约的衍生副本,但剩余供应量减少
  • 新发行的代币。

交易链一直持续到整个代币供应被发行为止。 请注意,任何人都可以调用该合约。

我们列出了一些分发策略作为示例。

速率限制

根据这项策略,任何人都可以领取代币,只要距离最后一次领取的时间超过 5 分钟即可。 合约如下。

export class BSV20Mint extends BSV20V2 {
    @prop(true)
    supply: bigint

    @prop()
    maxMintAmount: bigint

    @prop(true)
    lastUpdate: bigint

    @prop()
    timeDelta: bigint

    constructor(
        id: ByteString,
        max: bigint,
        dec: bigint,
        supply: bigint,
        maxMintAmount: bigint,
        lastUpdate: bigint,
        timeDelta: bigint
    ) {
        super(id, max, dec)
        this.init(...arguments)

        this.supply = supply
        this.maxMintAmount = maxMintAmount
        this.lastUpdate = lastUpdate
        this.timeDelta = timeDelta
    }

    @method()
    public mint(dest: Addr, amount: bigint) {
        // Check time passed since last mint.
        assert(
            this.timeLock(this.lastUpdate + this.timeDelta),
            'time lock not yet expired'
        )

        // Update last mint timestamp.
        this.lastUpdate = this.ctx.locktime

        // Check mint amount doesn't exceed maximum.
        assert(amount <= this.maxMintAmount, 'mint amount exceeds maximum')

        // Update supply.
        this.supply -= amount

        // If there are still tokens left, then
        // build state output inscribed with leftover tokens.
        let outputs = toByteString('')
        if (this.supply > 0n) {
            outputs += this.buildStateOutputFT(this.supply)
        }

        // Build FT P2PKH output to dest paying specified amount of tokens.
        outputs += BSV20V2.buildTransferOutput(dest, this.id, amount)

        // Build change output.
        outputs += this.buildChangeOutput()

        assert(hash256(outputs) == this.ctx.hashOutputs, 'hashOutputs mismatch')
    }
}

合约源代码

第 6-12 行强制执行速率限制。 第 26-30 行确保不超过供应量。 如果是,第 38-52 行将创建一个包含相同合约但具有更新状态的输出:剩余供应量。 第 55-58 行向目标地址发出令牌。

迷你工作量证明

该策略确保任何人都可以领取代币,只要她发现随机数满足某些特定的难度要求,就像比特币的工作量证明(PoW)一样。

export class Pow20 extends SmartContract {
    // ...

    @method(SigHash.ANYONECANPAY_ALL)
    public mint(
        nonce: ByteString,
        lock: ByteString,
        trailingOutputs: ByteString
    ) {
        if (len(this.id) == 0n) {
            this.id =
                this.ctx.utxo.outpoint.txid +
                int2ByteString(this.ctx.utxo.outpoint.outputIndex, 4n)
  }
        this.pow = this.validatePOW(nonce)
        const reward = this.calculateReward()
        this.supply -= reward
        let stateOutput = toByteString('')
        if (this.supply > 0n) {
            stateOutput = this.buildStateOutput(1n)
        }
        const rewardOutput = Utils.buildOutput(
            this.buildInscription(lock, reward),
            1n
        )

        const outputs: ByteString = stateOutput + rewardOutput + trailingOutputs
        assert(
            hash256(outputs) == this.ctx.hashOutputs,
            `invalid outputs hash ${stateOutput} ${rewardOutput} ${trailingOutputs}`
        )
    }

    @method()
    calculateReward(): bigint {
        let reward = this.reward
        if (this.supply < this.reward) {
            reward = this.supply
        }
        return reward
    }

    @method()
    validatePOW(nonce: ByteString): ByteString {
        const pow = hash256(this.pow + nonce)
        const test = rshift(Utils.fromLEUnsigned(pow), 256n - this.difficulty)
        assert(test == 0n, pow + ' invalid pow')
        return pow
    }
}
归功于: David Case

ICO

可以实施一项策略,以便任何人都可以通过以无需信任的方式将比特币发送到特定地址来接收代币,类似于首次代币发行(ICO)。 在上图中,添加了第三个输出用于比特币支付,该输出在合约中进行验证。

export class BSV20Mint extends SmartContract {
    // ...

    @method()
    public mint(dest: Addr, amount: bigint) {
        // If first mint, parse token id and store it in a state var
        if (this.isFirstMint) {
            this.tokenId =
                BSV20Mint.txId2Ascii(this.ctx.utxo.outpoint.txid) +
                toByteString('_', true) +
                BSV20Mint.int2Ascii(this.ctx.utxo.outpoint.outputIndex)
            this.isFirstMint = false
        }

        // Check if tokens still available.
        assert(
            this.totalSupply - this.alreadyMinted >= amount,
            'not enough tokens left to mint'
        )

        // Update already minted amount.
        this.alreadyMinted += amount

        let outputs = toByteString('')

        if (this.alreadyMinted != this.totalSupply) {
            // If there are still tokens left, then
            // build state output inscribed with leftover tokens.
            const leftover = this.totalSupply - this.alreadyMinted
            const transferInscription = BSV20Mint.getTransferInsciption(
                this.tokenId,
                leftover
            )
            const stateScript = slice(
                this.getStateScript(),
                this.prevInscriptionLen
            ) // Slice prev inscription
            outputs += Utils.buildOutput(transferInscription + stateScript, 1n)

            // Store next inscription length, so we know how much to slice in the next iteration.
            this.prevInscriptionLen = len(transferInscription)
        }

        // Build P2PKH output to dest paying specified amount of tokens.
        const script1 =
            BSV20Mint.getTransferInsciption(this.tokenId, amount) +
            Utils.buildPublicKeyHashScript(dest)
        outputs += Utils.buildOutput(script1, 1n)

        // Calculate total price for minted amount and enforce payment to ICO address.
        const priceTotal = this.icoPrice * amount
        outputs += Utils.buildPublicKeyHashOutput(this.icoAddr, priceTotal)

        // Build change output.
        outputs += this.buildChangeOutput()

        assert(hash256(outputs) == this.ctx.hashOutputs, 'hashOutputs mismatch')
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1192038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大厂面试题-MySQL为什么使用B+Tree作为索引结构

从几个方面来回答&#xff1a; 首先&#xff0c;常规的数据库存储引擎&#xff0c;一般都是采用B树或者B树来实现索引的存储。 (如图)因为B树是一种多路平衡树&#xff0c;用这种存储结构来存储大量数据&#xff0c;它的整个高度会相比二叉树来说&#xff0c;会矮很多。 而对…

【论文阅读】NeROIC:在线图像集合中对象的神经渲染

论文连接&#xff1a; NeROIC: Neural Rendering of Objects from Online Image Collections introduction 从在线图像集合中获取对象表示的新颖方法&#xff0c;从具有不同相机、照明和背景的照片中捕获任意对象的高质量几何形状和材料属性。这使得各种以对象为中心的渲染应…

AI:78-基于深度学习的食物识别与营养分析

🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在不断更新中,…

ssm+vue的疫情防控管理系统设计与实现(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的疫情防控管理系统设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网…

【AI】生成模型变得简单:了解它们的工作原理和不同类型

什么是生成模型&#xff1f; 在不断发展的人工智能领域&#xff0c;生成模型已成为人工智能技术最具吸引力和创造力的方面之一。这些模型是创意人工智能的核心&#xff0c;它们有能力生成各种内容&#xff0c;从栩栩如生的图像和引人入胜的文本到令人着迷的音乐和创新的艺术作…

webpack babel

构建工具 简介 当我们习惯了在node中编写代码的方式后&#xff0c;在回到前端编写html、css、js这些东西会感觉到各种的不便。比如&#xff1a;不能放心的使用模块化规范&#xff08;浏览器兼容性问题&#xff09;、即使可以使用模块化规范也会面临模块过多时的加载问题。我们…

MySQL字符串需要注意的事项

char(N)&#xff0c;N在0-255间 varchar(N)&#xff0c;N在0-65536间 需要注意N是字符&#xff0c;不是字节&#xff0c;英文字母一个字符一个字节&#xff0c;阿拉伯字母一个字符两个字节&#xff0c;中文日文一个字符三个字节&#xff0c;emoji是一个字符四个字节 当今移动端…

跨境电商:自养买家账号测评,你需要了解的细节

在跨境电商的浪潮中&#xff0c;自养买家账号测评已经成为了一种趋势。近期&#xff0c;不少跨境卖家咨询自养买家账号测评的相关问题&#xff0c;看来有必要再讲解一下卖家测评的一些细节。今天将着重介绍自养号测评的相关内容。 首先&#xff0c;什么叫做自养号测评呢&#x…

创建云端服务器

1.申请云端服务器 每个账户有三个月的免费试用 我的服务器选择是centos7 &#xff0c;别选成win了。 2.创建实例 创建实例的步骤&#xff0c;阿里云有文档 介绍 大致就是 左边点实例 -》 顶部选你申请服务器时的地区-》下面就出现一条实例-》点更多 -》要重置实例密码 -》同一…

海康工业相机如何提高相机帧率

影响帧率的因素 相机参数 帧率限制使能 像素格式 曝光时间 数据包大小&#xff08;网口&#xff09; 相机默认参数 ADC位深 系统环境设置

React进阶之路(四)-- React-router-v6、Mobx

文章目录 ReactRouter前置基本使用核心内置组件说明编程式导航路由传参嵌套路由默认二级路由404路由配置集中式路由配置 Mobx什么是Mobx环境配置基础使用计算属性&#xff08;衍生状态&#xff09;异步数据处理模块化多组件数据共享 ReactRouter 前置 在一开始前端开发都是单…

HBuilderX 运行Android App项目至雷电模拟器

一、下载安装HBuilderX HBuildeX官网 安装最新的正式版&#xff0c;或者点击历史版本查看更多版本&#xff1b;【ps&#xff1a;Alpha版本为开发版&#xff0c;功能更多&#xff0c;但是也不稳定&#xff0c;属于测试版本】 直接将压缩包解压&#xff0c;运行HBuildeX即可。 二…

凯美瑞 vs 太空船:Web3 游戏生长的两条路径

撰文&#xff1a;Teng Yan&#xff08;0xPrismatic&#xff09;&#xff0c;Delphi Digital 研究员 编译&#xff1a;TinTinLand 来源&#xff1a;https://0xprismatic.substack.com/p/my-short-web3-gaming-thesis 经常有人问我关于 Web3 游戏的看法&#xff0c;所以我想以这…

文本生成高精准3D模型,北京智源AI研究院等出品—3D-GPT

北京智源AI研究院、牛津大学、澳大利亚国立大学联合发布了一项研究—3D-GPT&#xff0c;通过文本问答方式就能创建高精准3D模型。 据悉&#xff0c;3D-GPT使用了大语言模型的多任务推理能力,通过任务调度代理、概念化代理和建模代理三大模块&#xff0c;简化了3D建模的开发流程…

vmware16.2内部win7联网

1、主机配置 前置条件&#xff1a;DHCP和NAT服务已启动 设置无线IP与虚拟机IP为自动获取 二者都是&#xff1a;右键-属性 选择IPv4 自动获取 2、虚拟机配置 设置虚拟机上网方式为NAT 菜单栏-虚拟机-设置 NMnet8改为NAT模式 菜单栏-编辑-虚拟网络编辑器 win7系统内部网…

Facebook广告被暂停是什么原因?广告账号被封怎么办?

许多做海外广告投放的小伙伴经常遇到一个难题&#xff0c;那就是投放的Facebook广告被拒或广告帐户被关闭赞停的经历&#xff0c;随之而来的更可能是广告账户被封&#xff0c;导致资金的损失。本文将从我自身经验&#xff0c;为大家分享&#xff0c;FB广告被暂停的原因有哪些&a…

Java多线程interrupt、interrupted、isInterrupted详解

一、概念 1.1 interrupt方法应用场景 用来打断正在阻塞的线程&#xff1a;sleep/wait/join打断正常的线程 1.2 interrupt() 方法 Thread类的实例方法&#xff0c;其作用是中断此线程&#xff08;此线程不一定是当前线程&#xff0c;而是指调用该方法的Thread实例所代表的线程…

【手写模拟Spring底层原理】

文章目录 模拟Spring底层详解1、结合配置类&#xff0c;扫描类资源1.1、创建需要扫描的配置类AppConfig&#xff0c;如下&#xff1a;1.2、创建Spring容器对象LyfApplicationContext&#xff0c;如下1.3、Spring容器对象LyfApplicationContext扫描资源 2、结合上一步的扫描&…

oracle11G在linux环境下的卸载操作

1.使用SQL*PLUS停止数据库 [oracleOracleTest oracle]$ sqlplus / as sysdba SQL> shutdown [immediate] SQL> exit2.停止Listener [oracleOracleTest oracle]$ lsnrctl stop3.停止HTTP服务 [rootOracleTest /root]# service httpd stop4.用su或者重新登录到root(如想…

bootstrap-fileinput拦截文件上传处理失败,根据后台返回数据处理

bootstrap-fileinput如何拦截后台数据&#xff0c;自定义处理业务逻辑 需要后台返回error字段&#xff0c;失败示例&#xff0c;注意&#xff1a;error必须有内容&#xff0c;不然默认也是成功&#xff0c; bootstrap-fileinput失败验证只需要 error 字段&#xff0c;其他附加…