盲拍合约:让竞拍更公平与神秘的创新解决方案

目录

前言        

一、盲拍合约是什么?

二、盲拍合约工作原理

1、合约创建与初始化

2、用户出价(Bid)

3、出价结束

4、披露出价(Reveal)

5、处理最高出价

6、结束拍卖

7、退款与提款

三、解析盲拍合约代码

1、数据结构

2、合约状态变量

3、事件

4、 错误处理

5、 修饰符

6、构造函数​编辑

7、出价功能

8、 披露出价

9、 处理最高出价

10、 提款功能

11、结束拍卖

四、盲拍合约用途

五、完整代码示例

总结


前言        

        盲拍合约是一种创新的拍卖机制,旨在通过保护买家的隐私和增强出价的公平性来提高交易效率。在这种合约中,参与者在未透露具体出价的情况下,基于对商品的描述或估值进行匿名竞标。盲拍合约不仅适用于艺术品和收藏品的拍卖,还能广泛应用于房地产、商品销售等多个领域,从而确保每位参与者都有平等的机会,降低了价格操纵的风险。

可访问文档:https://learnblockchain.cn/docs/solidity/0.5.9/examples/blind-auction.html#simple-auction

一、盲拍合约是什么?

        盲拍合约是一种在拍卖或交易中使用的合同形式,特别是在拍卖艺术品、收藏品或其他资产时,买家在未实际查看商品的情况下提交竞标或购买意向。这种合约的特点在于,买家对拍卖品的具体情况(如质量、状态等)没有事先了解,而是基于对商品的描述或估值来做出购买决定。

二、盲拍合约工作原理

1、合约创建与初始化

合约部署: 创建盲拍合约时,设置拍卖的受益人地址出价时间披露时间。这些参数定义了拍卖的基本规则。

2、用户出价(Bid)

匿名出价: 用户通过调用 bid 函数提交出价。用户提供三个参数:出价金额(value真假标记(fake秘密(secret

加密出价: 合约使用 keccak256 哈希函数计算出一个加密出价(blindedBid),该出价结合了用户的真实出价和其他参数。这确保了在拍卖期间用户的出价保持匿名

存储出价: 合约将加密出价和用户存款存储在 bids 映射中。

3、出价结束

结束出价: 在设置的出价时间结束后,用户无法再提交新的出价。这是通过 onlyBefore 修饰符控制的。

4、披露出价(Reveal)

出价披露: 在出价结束后,用户可以调用 reveal 函数,提交真实的出价信息,包括真实值、真假标记和秘密

验证出价: 合约验证用户披露的出价是否与之前提交的加密出价匹配。如果匹配且不是假出价,合约会更新最高出价并可能会退款。

退款机制: 对于不符合条件的出价,合约会保留存款。用户可以在出价被超越后提取退款。

5、处理最高出价

更新最高出价: 当用户披露有效的真实出价时,合约会检查是否高于当前最高出价。如果是,合约会更新最高出价和最高出价者的地址,并将之前的最高出价退还给原持有者。

6、结束拍卖

拍卖结束: 在披露时间结束后,合约通过 auctionEnd 函数结束拍卖。合约会将最高出价发送给受益人,并触发相应的事件记录结果。

7、退款与提款

提款功能: 用户可以通过调用 withdraw 函数提取未使用的存款,确保合约能够安全处理资金。

三、解析盲拍合约代码

1、数据结构

  • Bid: 定义了一个结构体,包含两个字段:
  • blindedBid: 存储用户加密的出价(bytes32 类型)。
  • deposit: 用户为出价提供的存款(uint 类型)。

2、合约状态变量

  • beneficiary: 合约的受益人地址,拍卖结束后,最高出价将转移到该地址。
  • biddingEnd: 表示出价结束的时间戳。
  • revealEnd: 表示出价披露结束的时间戳。
  • ended: 布尔值,指示拍卖是否已结束。
  • bids: 映射,每个用户地址对应一个出价数组,存储用户的所有出价。
  • highestBidder: 当前最高出价的用户地址。
  • highestBid: 当前最高出价的金额。
  • pendingReturns: 映射,存储待退还的金额。


3、事件

  • AuctionEnded: 当拍卖结束时触发的事件,记录赢家和最高出价。

4、 错误处理

定义了一些错误,描述可能的失败情况:

  • TooEarly: 调用函数过早。

  • TooLate: 调用函数过晚。

  • AuctionEndAlreadyCalled: 拍卖结束函数已被调用。

5、 修饰符

  • onlyBefore(uint time): 用于限制函数只能在指定时间之前调用。

  • onlyAfter(uint time): 用于限制函数只能在指定时间之后调用。


6、构造函数

  • constructor: 在合约部署时被调用,初始化受益人地址和拍卖的时间限制。

7、出价功能

bid(uint value, bool fake, bytes32 secret):

  • 用户通过此函数提交出价。出价通过 keccak256 生成加密值(blindedBid),将其与存款一起存储。

  • fake 参数用于指示出价是否为假,允许用户隐藏真实出价。


8、 披露出价

reveal(...):

  • 用户在出价披露阶段调用该函数,提交之前的出价信息(真实值、真假标记和秘密)。

  • 检查提交的出价是否与之前的加密出价匹配。如果匹配且不是假出价,可能会更新最高出价并退款。

  • 未能正确披露的出价将不会退还存款。


9、 处理最高出价

placeBid(address bidder, uint value):

  • 内部函数,用于检查新出价是否高于当前最高出价。

  • 如果新出价更高,更新最高出价并处理之前的最高出价的退款。


10、 提款功能

withdraw():

  • 允许用户提取之前被超越的出价。

  • 在提款前,将待退还金额设为零,以防止重入攻击。


11、结束拍卖

auctionEnd():

  • 在出价披露结束后调用,结束拍卖并将最高出价发送给受益人。

  • 触发 AuctionEnded 事件,记录赢家和最高出价。

四、盲拍合约用途

盲拍合约的用途广泛,主要适用于需要公平竞争和保护隐私的场景。以下是一些具体的应用领域:

  1. 艺术品拍卖: 在艺术品市场中,盲拍合约可以确保买家在出价时不受到其他买家影响,从而更真实地反映出对艺术品的价值评估。

  2. 房地产拍卖: 房地产拍卖中,买家可以在不透露出价的情况下参与竞标,避免价格上涨的心理战,促使更公平的交易。

  3. 商品销售: 在线市场和电商平台可以使用盲拍机制来售卖稀缺商品,确保所有参与者都有平等机会获取商品。

  4. 融资和投资: 在众筹或投资项目中,盲拍合约可以用来收集投资者的出价,确保所有出价在披露前保持匿名,促进公平竞争。

  5. 资源分配: 在需要分配有限资源的情况下(如频谱拍卖),盲拍合约能够确保各方以匿名方式出价,最大化资源的有效利用。

  6. 游戏和竞赛: 在游戏或竞赛中,盲拍合约可以用于奖励机制,确保参赛者在竞标奖励时不会受到其他参赛者的影响。

  7. 政府拍卖: 政府在拍卖公共资产(如土地、许可证)时,可以使用盲拍合约来确保出价过程的公正性和透明度。

        通过在这些场景中使用盲拍合约,可以提高交易的公平性、透明度和效率,同时保护参与者的隐私,减少潜在的欺诈行为。

五、完整代码示例

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.2;

contract BlindAuction {
    struct Bid {
        bytes32 blindedBid;
        uint deposit;
    }

    address payable public beneficiary;
    uint public biddingEnd;
    uint public revealEnd;
    bool public ended;

    mapping(address => Bid[]) public bids;

    address public highestBidder;
    uint public highestBid;

    // 可以取回的之前的出价
    mapping(address => uint) public pendingReturns;

    event AuctionEnded(address winner, uint highestBid);


    // Errors that describe failures.

    /// The function has been called too early.
    /// Try again at `time`.
    error TooEarly(uint time);
    /// The function has been called too late.
    /// It cannot be called after `time`.
    error TooLate(uint time);
    /// The function auctionEnd has already been called.
    error AuctionEndAlreadyCalled();

    /// 使用 modifier 可以更便捷的校验函数的入参。
    /// `onlyBefore` 会被用于后面的 `bid` 函数:
    /// 新的函数体是由 modifier 本身的函数体,并用原函数体替换 `_;` 语句来组成的。
    modifier onlyBefore(uint time) {
        if (block.timestamp >= time) revert TooLate(time);
        _;
    }
    modifier onlyAfter(uint time) {
        if (block.timestamp <= time) revert TooEarly(time);
        _;
    }

    constructor(
        uint biddingTime,
        uint revealTime,
        address payable beneficiaryAddress
    ) {
        beneficiary = beneficiaryAddress;
        biddingEnd = block.timestamp + biddingTime;
        revealEnd = biddingEnd + revealTime;
    }

    // blindedBid1=..keccak256(abi.encodePacked(2, true, bytes32("sdfadf")));


    /// 可以通过 `blindedBid` = keccak256(value, fake, secret)
    /// 设置一个秘密竞拍。
    /// 只有在出价披露阶段被正确披露,已发送的以太币才会被退还。
    /// 如果与出价一起发送的以太币至少为 “value” 且 “fake” 不为真,则出价有效。
    /// 将 “fake” 设置为 true ,然后发送满足订金金额但又不与出价相同的金额是隐藏实际出价的方法。
    /// 同一个地址可以放置多个出价。
    /*
    function bid(bytes32 blindedBid)
        external
        payable
        onlyBefore(biddingEnd)
    {
        bids[msg.sender].push(Bid({
            blindedBid: blindedBid,
            deposit: msg.value
        }));
    }
    */

    function bid(uint value, bool fake, bytes32 secret)
        external
        payable
        onlyBefore(biddingEnd)
    {
        // 计算 blindedBid 内部使用,仅供存储或其他用途
        bytes32 blindedBid = keccak256(abi.encodePacked(value, fake, secret));
        bids[msg.sender].push(Bid({
            blindedBid: blindedBid,
            deposit: msg.value
        }));
    }

    /// 披露你的秘密竞拍出价。
    /// 对于所有正确披露的无效出价以及除最高出价以外的所有出价,你都将获得退款。
    function reveal(
        uint[] calldata values,
        bool[] calldata fakeFlags,
        bytes32[] calldata secrets
    )
        external
        onlyAfter(biddingEnd)
        onlyBefore(revealEnd)
    {
        uint length = bids[msg.sender].length;
        require(values.length == length, "Mismatched values length");
        require(fakeFlags.length == length, "Mismatched fake flags length");
        require(secrets.length == length, "Mismatched secrets length");

        uint refund;
        for (uint i = 0; i < length; i++) {
            Bid storage bid = bids[msg.sender][i];
            (uint value, bool fake, bytes32 secret) =
                    (values[i], fakeFlags[i], secrets[i]);
            // 使用 abi.encodePacked 将多个参数打包成一个 bytes 类型
            if (bid.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
                // 出价未能正确披露
                // 不返还订金
                // console.log("披露失败!");
                continue;
            }
            refund += bid.deposit;
            if (!fake && bid.deposit >= value) {
                if (placeBid(msg.sender, value))
                    refund -= value;
            }
            // 使发送者不可能再次认领同一笔订金
            bid.blindedBid = bytes32(0);
        }
        // 使用 call 代替 transfer,推荐在 Solidity 0.8.x 版本中使用
        (bool success, ) = msg.sender.call{value: refund}("");
        require(success, "Refund failed");
    }

    // 这是一个 "internal" 函数, 意味着它只能在本合约(或继承合约)内被调用
    function placeBid(address bidder, uint value) internal
            returns (bool success)
    {
        if (value <= highestBid) {
            return false;
        }
        if (highestBidder != address(0)) {
            // 返还之前的最高出价
            pendingReturns[highestBidder] += highestBid;
        }
        highestBid = value;
        highestBidder = bidder;
        return true;
    }

    /// 取回出价(当该出价已被超越)
    function withdraw() external {
        uint amount = pendingReturns[msg.sender];
        if (amount > 0) {
            // 这里很重要,首先要设零值。
            // 因为,作为接收调用的一部分,
            // 接收者可以在 `call` 返回之前重新调用该函数。(可查看上面关于‘条件 -> 影响 -> 交互’的标注)
            pendingReturns[msg.sender] = 0;

            // 使用 call 代替 transfer,推荐在 Solidity 0.8.x 版本中使用
            (bool success, ) = msg.sender.call{value: amount}("");
            require(success, "Withdrawal failed");
        }
    }

    /// 结束拍卖,并把最高的出价发送给受益人
    function auctionEnd()
        external
        onlyAfter(revealEnd)
    {
        if (ended) revert AuctionEndAlreadyCalled();
        emit AuctionEnded(highestBidder, highestBid);
        ended = true;
        // 使用 call 代替 transfer,推荐在 Solidity 0.8.x 版本中使用
        (bool success, ) = beneficiary.call{value: highestBid}("");
        require(success, "Transfer to beneficiary failed");
    }
}

总结

        盲拍合约通过其独特的机制,实现了透明与隐私的平衡,推动了更公平的市场环境。合约的设计允许参与者在不泄露个人信息的情况下进行出价,有效防止了心理战和价格操控。在现代数字经济中,盲拍合约的应用潜力巨大,为各种交易场景提供了新方式,有助于提高交易的信任度和效率,促进了公平竞争。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

国产长芯微LUM6100高可靠性双通道双向I2C数字隔离器P2P替代ADUM1250 ADUM1251替代ISO1540 ISO1541

描述 LUM6100系列是高可靠性的双向l2C数字隔离器。提供符合UL1577的多种电气隔离耐压(3.75kVrms, 5kVrms)&#xff0c;且具有高电磁抗扰度和低辐射的特性。支持I2C时钟高达2MHZ&#xff0c;共模瞬态抗干扰度(CMTI)高达150kV/μs。宽供电范围可直接对接大多数MCU等数字接口,并且…

【C语言】使用结构体实现位段

文章目录 一、什么是位段二、位段的内存分配1.位段内存分配规则练习1练习2 三、位段的跨平台问题四、位段的应用五、位段使用的注意事项 一、什么是位段 在上一节中我们讲解了结构体&#xff0c;而位段的声明和结构是类似的&#xff0c;它们有两个不同之处&#xff0c;如下&…

AI资深导师指导-ChatGPT深度科研工作应用、论文撰写、数据分析及机器学习与AI绘图

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其在…

【PS2020】Adobe Photoshop 2020 中文免费版

photoshop 2020是全球最大的图像处理软件&#xff0c;为用户提供了广泛的专业级润饰工具套件&#xff0c;集成了专为激发灵感而设计的强大编辑功能&#xff0c;帮助用户制作出满意的图片效果&#xff0c;是很多摄影师、广告师等专业人员必备的一款图像及照片后期处理大型专业软…

大数据处理从零开始————4.认识HDFS分布式文件系统

1.分布式文件系统HDFS 1.1 认识HDFS 当单台服务器的存储容量和计算性能已经无法处理大文件时&#xff0c;分布式文件系统应运而生。什么是分布式系统&#xff0c;分布式系统是由多个独立的计算机或节点组成的系统&#xff0c;这些计算机通过网络连接&#xff…

重生之我在代码随想录刷算法第十九天 | 第77题. 组合、216.组合总和III、 17.电话号码的字母组合

参考文献链接&#xff1a;代码随想录 本人代码是Java版本的&#xff0c;如有别的版本需要请上代码随想录网站查看。 第77题. 组合 力扣题目链接 解题思路 这道题目乍一看可以用暴力解法解决&#xff0c;但如果k的数量增加那就需要套特别多的循环&#xff0c;所以这种组合类…

黑马linux笔记(转载)

学习链接 视频链接&#xff1a;黑马程序员新版Linux零基础快速入门到精通 原文链接&#xff1a;黑马程序员新版Linux零基础快速入门到精通——学习笔记 黑马Linux笔记 文章目录 学习链接01初识Linux1.1、操作系统概述1.1.1、硬件和软件1.1.2、操作系统1.1.3、常见操作系统 1.…

1.资源《Arduino UNO R3 proteus 仿真工程》说明。

资源链接&#xff1a; Arduino UNO R3 proteus 仿真工程 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;proteus工程、原理图、仿真程序。 3.内容展示 4.简述 该文件为proteus工程&#xff0c;用于Arduino uno r3仿真。 因为软件自动运行&#xff0c;所以最小…

编译链接的过程发生了什么?

一&#xff1a;程序的翻译环境和执行环境 在 ANSI C 的任何一种实现中&#xff0c;存在两个不同的环境。 第 1 种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 第 2 种是执行环境&#xff0c;它用于实际执行代码 也就是说&#xff1a;↓ 1&#xff1…

CVE-2024-9014 pgAdmin4 OAuth2 client ID与secret敏感信息泄漏漏洞

文章目录 免责声明漏洞描述搜索语法漏洞复现nuclei修复建议 免责声明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 漏洞描述 pgAdmin4 是开源数据库 PostgreSQL 的图形管理工具攻击者可构造恶意…

OpenCV库模块解析

1.OpenCV库每个模块解析 2.OpenCV的常用函数 它为计算机视觉应用程序提供了一个通用的基础设施&#xff0c;并加速了在商业产品中使用机器感知。作为BSD许可的产品&#xff0c;OpenCV使企业可以很容易地利用和修改代码。该库拥有超过2500个优化算法&#xff0c;其中包括经典和最…

Hotspot是什么?

Hotspot 简单来说&#xff0c;JVM的一种。 一、HotSpot 的官方定义 HotSpot 是 Oracle 公司开发的一个高性能的 Java 虚拟机&#xff08;JVM&#xff09;。它通过一系列先进的技术和优化手段&#xff0c;为 Java 应用程序提供高效的运行环境&#xff0c;实现了跨平台的代码执行…

页面引导解决方案分享

前言 本文主要介绍的是我们在项目中有时候会遇到需要一步一步引导用户操作的使用场景&#xff0c;类似于新手教学的操作指引&#xff0c;给出的解决方案是Intro.js 库&#xff0c;通过此库创建引导式用户体验。 介绍 Intro.js 是一个轻量级的 JavaScript 库&#xff0c;用于…

《向量数据库指南》深度解析:CLIP模型与Mlivus Cloud在多模态搜索中的强强联合

在当今这个信息爆炸的时代,如何高效、准确地从海量数据中检索出用户所需的信息,成为了摆在我们面前的一大挑战。而多模态搜索,作为一种能够同时处理图像、文本、音频等多种类型数据的搜索技术,正逐渐成为解决这一问题的关键。作为大禹智库的向量数据库高级研究员,同时也是…

【玩转 JS 函数式编程_008】3.1.2 JavaScript 函数式编程筑基之:箭头函数——一种更流行的写法

文章目录 3.1.2 箭头函数——更流行的方式 Arrow functions - the modern way1. 返回值 Returning values2. this 值的处理 Handling the this value3. arguments 的处理 Working with arguments4. 单参数还是多参数&#xff1f; One argument or many? 写在前面 故天将降大任…

【rCore OS 开源操作系统】Rust 字符串(可变字符串String与字符串切片str)

【rCore OS 开源操作系统】Rust 语法详解: Strings 前言 这次涉及到的题目相对来说比较有深度&#xff0c;涉及到 Rust 新手们容易困惑的点。 这一次在直接开始做题之前&#xff0c;先来学习下字符串相关的知识。 Rust 的字符串 Rust中“字符串”这个概念涉及多种类型&…

k8s 中的金丝雀发布(灰度发布)

目录 1 什么是金丝雀发布 2 Canary 发布方式 3 Canary 两种发布方式实操 3.1 准备工作 3.1.1 将 nginx 命名两个版本 v1 与 v2 3.1.2 暴露端口并指定微服务类型 3.1.3 进入 pod 修改默认发布文件 3.1.4 测试 service 是否正常 3.2 基于权重的灰度发布 3.2.1 创建 Igress 资源类…

分享我“Excel 表格”关键字的博客笔记(python脚本全程自动)

Python脚本全程自动&#xff0c;全部Python内建工具脚本纯净。 (笔记模板由python脚本于2024年10月05日 19:51:06创建&#xff0c;本篇笔记适合喜欢Excel和Python的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大…

ubuntu双系统分区划分

EFI系统分区&#xff08;Windows&#xff09;&#xff1a;自Windows 8起&#xff0c;UEFI模式下的BIOS使用该分区。简单来说&#xff0c;它用于存储已安装系统的EFI引导程序。此分区在资源管理器中无法查看&#xff0c;因为它没有驱动器号&#xff0c;但它必须存在&#xff0c;…

前端登录页面验证码

首先&#xff0c;在el-form-item里有两个div&#xff0c;各占一半&#xff0c;左边填验证码&#xff0c;右边生成验证码 <el-form-item prop"code"><div style"display: flex " prop"code"><el-input placeholder"请输入验证…