本项目是一个基于 Solidity 和 React 的去中心化应用。它允许“公证人”创建竞猜活动,用户使用 ERC20 代币 (BetToken) 进行下注,并获得一个 ERC721 NFT (BetTicket) 作为凭证。
核心逻辑在 EasyBet.sol 合约中,它负责管理活动、奖池以及一个二级市场。
-
公证人创建竞猜
- 功能:只有合约的部署者(公证人)才能创建新的竞猜活动。
- 实现:
EasyBet合约中的createActivity函数受到了onlyNotary修饰符的保护。前端NotaryAdmin组件 会在账户匹配时显示此管理面板。
-
用户下注与 NFT 凭证
- 功能:用户可以选择一个未结算的活动,使用
BetToken对特定选项下注,并收到一张 NFT 彩票。 - 实现:
EasyBet合约的placeBet函数会接收用户的BetToken,然后调用BetTicket合约的mintTicket函数,为用户铸造一张NFT。这张 NFT 通过ticketInfo映射 记录了活动ID、选项和下注金额。
- 功能:用户可以选择一个未结算的活动,使用
-
活动结算与奖金分配
- 功能:公证人宣布获胜选项后,持有获胜 NFT 的用户可以领取奖金。
- 实现:公证人调用
resolveActivity来锁定获胜选项。获胜者调用claimWinnings,合约会根据该 NFT 的下注金额占总获胜池的比例来计算奖金,并发放BetToken。领奖后,该 NFT 凭证会被销毁。
- 功能:允许任何用户免费获取一定数量的
BetToken用于测试。 - 实现:
BetToken.sol合约中实现了一个faucet函数,调用时会为msg.sender铸造(mint)1000 个代币。前端WalletInfo组件 提供了一个按钮来触发此功能。
- 功能:允许用户在活动结算前自由买卖他们持有的
BetTicketNFT。 - 实现:
- 挂单/取消挂单:
listTicket和unlistTicket函数允许 NFT 持有者(在approve授权后)将其彩票上架或下架。 - 购买彩票:
buyTicket函数实现了原子化交易:它首先将买家的BetToken转给卖家,然后将卖家的BetTicketNFT 转给买家。 - 订单簿管理:为了让前端能够高效遍历所有挂单,
EasyBet.sol使用了一个数组_listedTokenIds和一个映射_listedTokenIndex。在移除订单时,_removeListedToken函数将数组的最后一个元素移到被删除元素的位置并更新其索引,从而维护订单簿。 - 前端展示:前端的
refreshAll函数会获取_listedTokenIds列表,然后并发获取每张彩票的价格 (sellOrders) 和详细信息 (ticketInfo),最终在OrderBook组件中向买家完整展示活动、选项和价格。
- 挂单/取消挂单:
运行成功后看到初始页面,点击连接到metamask会自动连接到metamask的活动账户,这里先选择“公证人”账户

为方便测试,每个账户都可以无限制领取BET代币,比如这里点击领取按钮

活动创建后,每个账户都可以下注,下注之后可以在我的彩票中看到

补充如何完整运行你的应用。
-
在本地启动ganache应用。
-
在
./contracts中安装需要的依赖,运行如下的命令:npm install
-
在
./contracts中编译合约,运行如下的命令:npx hardhat compile
-
部署命令:
npx hardhat run scripts/deploy.ts --network ganache
这步会输出三个地址,需要分别写入
./frontend/src/ethers.ts开头的三个变量处 -
将编译新生成的typechain-types复制到
./frontend/src/ -
在
./frontend中安装需要的依赖,运行如下的命令:npm install
-
在
./frontend中启动前端程序,运行如下的命令:npm start







