Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
网络与协议指南阅读约 11 分钟

Play-to-Earn 加密游戏:架构、验证与衡量

一份技术指南,介绍 Play-to-Earn 加密游戏如何在链上运作、如何验证奖励与合约,以及如何衡量自身收益和基础设施可靠性。

TL;DR

Play-to-Earn 加密游戏是指奖励、资产或所有权记录在区块链上结算的游戏,通常以同质化代币或 NFT 的形式呈现。赚取机制的可信度取决于合约以及你用来读取它们的数据路径,因此本指南聚焦于链上机制、如何自行验证游戏的奖励合约,以及如何衡量收益和 RPC 可靠性,而不是轻信营销宣传。文中包含可运行的只读脚本、结果表流程、故障排查和权衡取舍。具体的端点与提供商选择有意留给 RPC Assistant。

直接答案与范围

Play-to-Earn 加密游戏是指至少部分奖励循环——代币支付、物品所有权或市场结算——记录在区块链上的电子游戏。游戏客户端可能是中心化的,但资产层不是。这一区别很重要:一款游戏可以自称 Play-to-Earn,而其奖励纯粹是链下数据库条目;一款游戏也可以完全链上,但在经济上毫无吸引力。

本文涵盖技术层面:链上组件通常是什么、如何验证游戏的合约和奖励流程、如何衡量你实际赚取了多少,以及在此过程中如何保持 RPC 数据路径可靠。本文不对游戏进行排名,也不承诺收入。关于端点与提供商选择,请使用 RPC Assistant,而不要将本页视为提供商列表。

  • 涵盖范围:合约验证、奖励流程检查、收益衡量、RPC 可靠性。
  • 不涵盖范围:游戏推荐、代币价格预测、保证盈利的声明。

假设与前提条件

以下流程假设你有一个与游戏交互过的钱包地址、游戏结算所在的链,以及对 RPC 端点的读取权限。任何验证步骤都不需要私钥;此处所有操作均为只读。将任何签名密钥保存在环境变量中,切勿将其粘贴到脚本或共享终端中。

你还应从游戏文档或经过验证的区块浏览器中了解游戏的官方合约地址。在社交帖子中的地址与浏览器的已验证源代码或项目已发布文档匹配之前,应将其视为不可信。

  • 一个你想要审计的、有资金或历史记录的钱包地址。
  • 该链的链 ID 和 RPC_URL。
  • 如果你想运行脚本,需要 Node.js 18+ 或 Python 3.10+。
  • 可选:用于合约源代码验证的浏览器 API 密钥。

心智模型:赚取实际发生在哪里

大多数 Play-to-Earn 加密游戏分为三层。游戏客户端(通常是普通的 Web 或移动应用)运行游戏玩法。后端或游戏服务器验证操作并决定谁有资格获得奖励。区块链层持有代币合约、NFT 合约、市场,有时还有按计划或在领取时支付的奖励分发合约。

赚取机制存在于服务器与链的边界处。如果服务器签署支付,链会记录它们,但不会独立验证游戏玩法。如果游戏完全链上,合约逻辑强制执行规则,但游戏玩法受 gas 和出块时间的限制。了解游戏使用哪种模型,可以告诉你哪些可以验证、哪些必须信任。

这也是为什么“免费赚取”的说法值得审视:奖励分发合约只能从有资金的池中支付,而该池的余额和释放计划在链上是可见的。如果池是空的,或者释放量相对于玩家基数很小,那么在你投入时间之前,经济状况就已经可见了。

验证游戏的合约和奖励池

首先确认代币和分发合约已在区块浏览器上验证。已验证的源代码让你可以阅读 mint、transfer 和 claim 函数,而不是从字节码中猜测。然后读取分发合约的代币余额以及任何释放或领取参数。

以下只读脚本使用 ethers 查询代币余额和基本元数据。将 RPC_URL、TOKEN_ADDRESS 和 HOLDER_ADDRESS 替换为你自己的值。它不签署任何内容。

// npm i ethers
import { JsonRpcProvider, Contract, formatUnits } from "ethers";

const RPC_URL = process.env.RPC_URL;
const TOKEN_ADDRESS = "0xYourTokenAddress";
const HOLDER_ADDRESS = "0xRewardDistributorOrGameAddress";

const erc20Abi = [
  "function name() view returns (string)",
  "function symbol() view returns (string)",
  "function decimals() view returns (uint8)",
  "function balanceOf(address) view returns (uint256)",
  "function totalSupply() view returns (uint256)"
];

const provider = new JsonRpcProvider(RPC_URL);
const token = new Contract(TOKEN_ADDRESS, erc20Abi, provider);

const [name, symbol, decimals, balance, supply] = await Promise.all([
  token.name(),
  token.symbol(),
  token.decimals(),
  token.balanceOf(HOLDER_ADDRESS),
  token.totalSupply()
]);

console.log({ name, symbol, decimals });
console.log("Holder balance:", formatUnits(balance, decimals));
console.log("Total supply:", formatUnits(supply, decimals));
console.log("Holder share:", Number(balance) / Number(supply));

检查你自己的奖励历史

要衡量游戏实际支付给你多少,请拉取你的地址作为接收方的代币转账日志。这提供了一个独立于游戏内仪表盘的事实账本。下面的 Python 示例使用 web3.py,并在一个区块范围内将 ERC-20 Transfer 事件过滤到你的地址。根据链的出块时间调整范围,以使查询保持在提供商限制内。

如果你的提供商限制了 getLogs 范围,请将范围拆分为块并分页。可靠的端点在这里很重要,因为截断的日志查询会静默地低估你的收益。

# pip install web3
import os
from web3 import Web3

RPC_URL = os.environ["RPC_URL"]
TOKEN_ADDRESS = Web3.to_checksum_address("0xYourTokenAddress")
WALLET = Web3.to_checksum_address("0xYourWallet")
START_BLOCK = 0
END_BLOCK = "latest"

w3 = Web3(Web3.HTTPProvider(RPC_URL))
transfer_topic = w3.keccak(text="Transfer(address,address,uint256)").hex()
wallet_topic = "0x" + "0" * 24 + WALLET[2:].lower()

logs = w3.eth.get_logs({
    "fromBlock": START_BLOCK,
    "toBlock": END_BLOCK,
    "address": TOKEN_ADDRESS,
    "topics": [transfer_topic, None, wallet_topic],
})

total = 0
for log in logs:
    amount = int.from_bytes(log["data"], "big")
    total += amount

print(f"Transfers received: {len(logs)}")
print(f"Raw total: {total}")

使用结果表衡量收益

不要依赖单一快照。构建一个小型结果表,以便在同一基础上比较游戏和时间段。为你评估的每个游戏记录以下列,并且只填写你实际观察到的值。

| 游戏 | 链 | 奖励代币 | 收到的转账 | 原始代币总量 | 代币小数位 | 人类可读总量 | 观察窗口(区块) | 备注 |

| --- | --- | --- | --- | --- | --- | --- | --- | --- |

| (你的数据) | (你的数据) | (你的数据) | (你的数据) | (你的数据) | (你的数据) | (你的数据) | (你的数据) | (你的数据) |

留空单元格而不是估算。使用代币的小数位转换原始总量,并注明奖励是领取的还是自动分发的。如果你想要法币估值,请单独记录价格来源和时间戳,以便表格保持可审计。此流程产生可比较的数字,而无需编造基准。

保持 RPC 数据路径可靠

日志查询、余额检查和合约读取都依赖于端点返回完整且一致的数据。公共端点会积极限流,被限流的请求可能看起来像空结果。对于你打算保留的任何测量,请使用具有可预测限制和重试逻辑的端点。

下面的模式用超时和有界重试包装 JSON-RPC 调用。它有意保持简单;生产工具还应记录端点和请求 ID,以便故障可追溯。

import os, time, requests

RPC_URL = os.environ["RPC_URL"]

def rpc(method, params, retries=3):
    payload = {"jsonrpc": "2.0", "id": 1, "method": method, "params": params}
    for attempt in range(retries):
        try:
            r = requests.post(RPC_URL, json=payload, timeout=10)
            r.raise_for_status()
            body = r.json()
            if "error" in body:
                raise RuntimeError(body["error"])
            return body["result"]
        except Exception as e:
            if attempt == retries - 1:
                raise
            time.sleep(2 ** attempt)

print(rpc("eth_blockNumber", []))

预期的验证结果

运行脚本后,你应该能够对你正在评估的任何游戏陈述三个事实:奖励代币的身份和小数位、分发合约的当前余额和供应份额,以及你的钱包在定义的区块窗口内收到的转账数量和大小。如果其中任何一项无法确定,请将赚取声明视为未经验证。

健康的结果还包括干净的 RPC 响应,没有耗尽重试。如果你的重试包装器反复触发,问题在于端点,而不是游戏。

常见故障排查

此工作流中的大多数故障属于几类。在得出关于游戏经济状况的结论之前,先解决原因。

  • 日志结果为空:确认代币地址,以及你的钱包主题是否正确填充并转为小写。
  • 范围错误:将 getLogs 拆分为更小的区块窗口,或使用支持更宽范围的提供商。
  • 速率限制:添加退避、降低并发,或迁移到专用端点。
  • 错误的链:在信任任何余额之前验证链 ID。
  • 未验证的合约:读取事件和余额,但不要仅从字节码推断函数行为。

局限性与权衡

链上验证告诉你支付了什么以及存在哪些合约;它不会告诉你游戏玩法是否有趣、游戏是否会持续,或者代币价格是否会保持。完全链上的游戏以灵活性换取可验证性,而服务器签名的游戏以可验证性换取更丰富的游戏玩法。两种模型本质上都没有更好,但它们需要不同程度的信任。

衡量也有局限性。较短的观察窗口可能会错过季节性释放,而单个钱包可能无法代表更广泛的玩家群体。将你的表格视为关于你自己经验的证据,而不是市场预测。

后续步骤

一旦你能够验证合约并衡量奖励,就可以扩展工作流:添加 NFT 合约检查以确认物品所有权,比较不同游戏的奖励分发合约余额,并跟踪你的 RPC 错误率随时间的变化。关于端点选择,请参阅 <a href="/en/api-service">API 服务概览</a> 和 <a href="/en/pricing/rpc">RPC 定价</a>,并使用 RPC Assistant 获取具体的提供商选择。如果你运行自己的基础设施,请查看 <a href="/en/dedicated-node">专用节点</a> 和 <a href="/en/learn/blockchain-node-hosting-guide">区块链节点托管指南</a>。要了解特定游戏背后的网络,请浏览 <a href="/en/networks">支持的网路</a> 和 <a href="/en/learn/rpc-endpoints-guide">RPC 端点指南</a>。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始