如果你是从 proposal 页面点击 How to vote? 进入文档,建议先看:
tools/vote.ts 是当前仓库内的交互式投票辅助脚本,用于向 SourceDaoCommittee 提交 support / reject 交易。
它的定位是:
- 面向真实链上治理操作的辅助工具
- 默认服务于当前
opmain的SourceDAO - 依赖后台接口拉取 proposal 参数
- 目前只覆盖少数 proposal 类型
- 已提供一版不改合约的离线签名辅助流程
它不是一个通用治理 CLI,也不是一个离线参数构造器。
推荐入口:
npx hardhat run tools/vote.ts --network opmain兼容入口:
npx hardhat run vote.ts --network opmain根目录的 vote.ts 只是一个兼容转发入口,后续应优先使用 tools/vote.ts。
离线签名入口:
npx hardhat run tools/vote_offline.ts --network opmain离线签名流程说明见:
- Node.js 使用
v22+ - 在仓库根目录执行过
npm i - 在
hardhat.config.ts里配置了目标网络和投票私钥 - 投票私钥放在对应网络
accounts数组的第一位 - 操作者已经确认自己连接的是正确网络和正确 DAO 地址
示例:
networks: {
opmain: {
url: "your opmain endpoint url",
accounts: [
"your private key, begin with 0x",
]
}
}当前脚本保留了默认地址和默认后台接口,但支持用环境变量覆盖:
-
SOURCE_DAO_ADDRESS- 默认值:当前
opmainDAO 地址 - 用途:切换到另一个 DAO 实例
- 默认值:当前
-
SOURCE_DAO_API_BASE- 默认值:
https://dao.buckyos.org/api - 用途:切换到另一个 proposal backend
- 默认值:
示例:
SOURCE_DAO_ADDRESS=0xYourDaoAddress \
SOURCE_DAO_API_BASE=https://dao.example.org/api \
npx hardhat run tools/vote.ts --network opmain当前推荐使用两层 JSON 配置:
tools/config/profiles/<profile>.jsontools/config/local.json
职责划分:
-
profile- 放部署级、全工具通用的配置
- 例如
daoAddress、proposalApiBase
-
local- 放操作者本地偏好
- 例如
voterAddress、offline.*、status.output
示例文件:
默认查找顺序:
tools/config/profiles/opmain.jsontools/config/local.json- 旧兼容配置:仓库根目录
vote.config.json - 旧兼容配置:
tools/vote.config.json
可选环境变量:
-
SOURCE_DAO_PROFILE- 指定 profile 名称,例如
opmain
- 指定 profile 名称,例如
-
SOURCE_DAO_PROFILE_PATH- 显式指定 profile 配置文件路径
-
SOURCE_DAO_LOCAL_CONFIG- 显式指定本地配置文件路径
-
SOURCE_DAO_CONFIG- 旧单文件配置兼容入口,优先级高于 profile/local
优先级:
- 环境变量
SOURCE_DAO_CONFIG指向的旧单文件配置local配置profile配置- 代码默认值
如果配置文件里的 offline.* 路径使用相对路径,当前实现会按该配置文件所在目录解析。
当前第一版只支持 JSON,还没有接入 TOML 解析。
- 运行脚本
- 检查输出的网络名、RPC endpoint、DAO 地址、签名地址
- 输入 proposal id
- 检查链上 proposal 的基础信息
- 选择
support或reject - 脚本从后台拉取 proposal 参数
- 检查后台返回的参数是否与预期一致
- 输入
y确认,发送链上交易 - 等待交易确认
当前仓库已经提供一个最小版离线签名流程:
- 在线机器
prepare - 离线机器
sign - 在线机器
broadcast
这个版本不修改合约,只是把真实链上交易拆成准备、签名、广播三步。
详细说明见:
脚本目前只支持以下 proposal 参数编码:
createProjectacceptProjectupgradeContractsetCommittees
如果后台返回其他 proposal 类型,脚本会直接报错并退出。
这意味着:
- 工具能力受限于链上 proposal 类型和后台返回格式
- 新增 proposal 类型时,需要同步更新
tools/vote.ts
当脚本检测到目标 proposal 是 full proposal 时,会显示当前地址的 DevToken / NormalToken 余额,以及按当前 devRatio 计算出的一个估算票数。
这里需要明确:
- 这个数字只是当前状态下的提示信息
- 它不是最终治理结果的权威票数
- 最终结算仍然以合约的链上逻辑为准
当前仓库已经把 full proposal 的统一快照问题单独记录在:
虽然脚本现在支持用环境变量覆盖 DAO 地址和后台 API,但默认行为仍是指向当前 opmain 部署。
脚本不会在本地自行恢复完整 proposal 参数,而是调用:
https://dao.buckyos.org/api/proposal/:id
因此只要后台不可用、返回字段变化、或 proposal schema 演进,脚本就可能失败。
脚本只做投票,不负责:
- proposal 列表查询
- 历史交易索引
- 参数对比和差异审计
endFullPropose(...)的批量结算
脚本目前仍属于运维辅助工具,主要依赖人工执行和链上反馈验证。后续如果继续扩展 proposal 类型,建议把参数编码和后端响应解析拆出来做单测。
- 检查
hardhat.config.ts里对应网络是否配置了accounts - 检查投票私钥是否在第一个位置
- 检查 proposal id 是否正确
- 检查连接到的 DAO 地址是否正确
- 检查连接的网络是否正确
- 说明后台返回的 proposal 类型当前脚本还不支持
- 需要补充
tools/vote.ts里的参数编码逻辑
- 这是 full proposal 下的链上拒绝
- 当前地址在该提案结算语义下没有有效票权
- 当前地址已经对该 proposal 提交过投票
- 后台返回的参数与链上 proposal 期望编码不一致
- 或脚本本地的 proposal 参数编码逻辑已经落后于合约
如果继续扩展治理辅助工具,建议按下面的方向演进:
- 把 proposal 参数编码拆成独立模块
- 为后端响应格式加显式 schema 校验
- 增加网络和
chainId防呆检查 - 增加更多 proposal 类型支持
- 为工具层单独增加测试
- 把其他辅助脚本逐步归拢到
tools/