Skip to main content
本页是质押预编译合约接口的技术参考。要获取面向开发者的常见工作流指南,请访问 概述

地址

函数与选择器

常量

状态修改函数

addValidator

创建一个关联委托者账户的验证者,并返回结果 validatorId 函数选择器
函数签名
参数
  1. payload - 由以下字段组成,以大端字节序打包在一起(等价于 Solidity 中的 abi.encodePacked()):
    • bytes secpPubkey(用于共识的唯一 SECP 公钥)
    • bytes blsPubkey(用于共识的唯一 BLS 公钥)
    • address authAddress(用于验证者委托者账户的地址。该地址对验证者的质押金额拥有提现权限)
    • uint256 amount(验证者自我质押的金额。必须等于 msg.value)
    • uint256 commission(向委托者收取的佣金,乘以 1e18,例如 10% = 1e17)
  2. signedSecpMessage - 对 payload 的 SECP 签名
  3. signedBlsMessage - 对 payload 的 BLS 签名
Gas 成本 505,125 行为 该函数首先解包 payload 以获取 secpPubkeyblsPubkeyauthAddressamountcommission,然后验证 signedSecpMessagesignedBlsMessage 对应于由相应 SECP 和 BLS 私钥签名的 payload。
  • 验证者必须同时提供唯一的 BLS 密钥和唯一的 SECP 密钥。任何包含重复公钥的提交都会回滚。
  • 两个签名(signedSecpMessagesignedBlsMessage)都必须有效,且都必须是对 payload 的签名。
  • 多个验证者可以共享同一个 authAddress
  • msg.value 必须大于或等于 MIN_AUTH_ADDRESS_STAKE,否则调用将回滚。
  • 如果 msg.value 还大于或等于 ACTIVE_VALIDATOR_STAKE,则该验证者将在未来激活:
    • 如果 addValidator 在边界区块之前调用,则在纪元 n+1;
    • 否则将在纪元 n+2 激活。
用法 以下是组装 payload 并签名的示例:

delegate

如果委托者账户不存在则创建,并增加委托者的余额。 函数选择器
函数签名
参数
  1. validatorId - 委托者希望委托的验证者的 ID
  2. msg.value - 要委托的金额
Gas 成本 260,850 行为
  • 委托者账户由 msg.sender 决定。
  • validatorId 必须对应一个有效的验证者。
  • msg.value 必须 >= DUST_THRESHOLD
  • 如果此次委托使验证者的总质押超过 ACTIVE_VALIDATOR_STAKE,并且该验证者尚不在 execution_valset 中,则会被添加进去。
  • 委托者的质押变为活跃
    • 若请求在边界区块之前,则在纪元 n+1 生效
    • 否则在纪元 n+2 生效

undelegate

从委托者账户扣除 amount 并将其移入一个提现请求对象,在 WITHDRAWAL_DELAY 个纪元的挂起状态之后,资金即可通过 withdraw 函数领取。 函数选择器
函数签名
参数
  1. validatorId - 发送者此前已委托的验证者的 ID,我们要从该验证者移除委托
  2. amount - 要解除委托的金额,以 Monad wei 计
  3. withdrawId - 0 到 255(含)之间的整数,作为委托者提现的标识符。对于每个 (validator, delegator) 元组,最多可有 256 个未完成的提现请求
Gas 成本 147,750 行为
  • 委托者账户由 msg.sender 决定。
  • validatorId 必须对应一个发送者此前已委托过的有效验证者
  • 委托者必须拥有 >= amount 的质押。
  • 如果提现导致 Val(validatorId).stake() 降至 ACTIVE_VALIDATOR_STAKE 以下,则该验证者将被安排从 valset 中移除。
  • 如果验证者的 authAddress 解除足够多的自身质押,使其降至 MIN_AUTH_ADDRESS_STAKE 以下,则该验证者将被安排从 valset 中移除。
  • 如果存在具有相同 withdrawId 的待处理提现,该函数会回滚。调用 withdrawwithdrawId 可复用。
  • 委托者只能在质押已激活后才能移除该质押。这是委托者结构体中的 stake 字段。待生效的委托在激活前不能被移除。
  • 委托者的质押在 valset 中变为非活跃
    • 若请求在边界区块之前,则在纪元 n+1 生效
    • 否则在纪元 n+2 生效
  • 委托者的质押变为可提现,因此不再受罚没约束
    • 若请求在边界区块之前,则在纪元 n + 1 + WITHDRAWAL_DELAY
    • 否则在纪元 n + 2 + WITHDRAWAL_DELAY
timeline of undelegation and withdrawal

质押可提现性相对于 undelegate 命令的时间线

withdraw

完成一次解除委托操作(以调用 undelegate 函数开始),将金额发送给 msg.sender,前提是已经过足够的纪元。 函数选择器
函数签名
参数
  1. validatorId - 发送者此前已委托的验证者的 ID,我们之前对该验证者发出了 undelegate 命令
  2. withdrawId - 委托者此前创建的提现的标识符;即之前提供给 undelegate 的相同 id。对于每个 (validator, delegator) 元组,最多可有 256 个未完成的提现请求。
Gas 成本 68,675 行为
  • 委托者为 msg.sender。提现由 msg.sendervalidatorIdwithdrawId 标识
  • 一旦解除委托完成且提现延迟已过,即可执行提现操作:
    • 若解除委托请求在边界区块之前,则在纪元 n + 1 + WITHDRAWAL_DELAY
    • 否则在纪元 n + 2 + WITHDRAWAL_DELAY

compound

将委托者已累积的奖励转换为额外的质押。 函数选择器
函数签名
参数
  1. validatorId - 发送者此前已委托的验证者的 ID,我们要为其复投奖励
Gas 成本 289,325 行为
  • 用于复投的账户由 msg.sender 决定。如果委托者账户不存在,则调用回滚
  • validatorId 必须对应一个发送者此前已委托过的有效验证者
  • 委托者的奖励在 valset 中变为活跃
    • 若请求在边界区块之前,则在纪元 n+1 生效
    • 否则在纪元 n+2 生效.

claimRewards

允许委托者领取奖励而非 复投 它们。 函数选择器
函数签名
参数
  1. validatorId - 发送者此前已委托的验证者的 ID,我们要为其领取奖励
Gas 成本 155,375 行为
  • validatorId 必须对应一个发送者此前已委托过的有效验证者
  • 如果该 (validatorId, msg.sender) 元组对应的委托者账户不存在,则调用回滚
  • 委托者累积的奖励会转入其委托账户

changeCommission

允许验证者的 authAddress 修改该验证者的佣金。 函数选择器
函数签名
参数
  1. validatorId - 希望更改佣金率的验证者的 ID
  2. commission - 从区块奖励中收取的佣金率,以 1e18 为单位表示(例如 10% = 1e17)
Gas 成本 39,475 行为
  • msg.sender 必须是相应验证者 Id 的 authAddress
  • 佣金不能设置为大于 MAX_COMMISSION(当前为 100%)。
  • 佣金变更在以下纪元生效:
    • 如果请求不在纪元延迟轮次内,则在纪元 n+1
    • 如果请求在纪元延迟轮次内,则在纪元 n+2

externalReward

允许任何人向特定验证者的质押者发送额外的 MON,通常由验证者自己调用以将额外的小费分享给其委托者。 函数选择器
函数签名
参数
  1. validatorId - 验证者的 ID
  2. msg.value - 要添加到未领取奖励中的 MON
Gas 成本 66,575 行为
  • 只能对当前在共识验证者集中的验证者调用;否则交易将回滚。
  • msg.value 必须介于 1 MON 与 1,000,000 MON 之间;否则交易将回滚。
  • 此处不会从中扣除佣金并转入验证者的 auth_address。如果您希望扣除一部分,应在发送前先扣除。

视图函数

由于质押预编译合约只允许 CALL,所有视图函数都被赋予默认的 nonpayable 状态可变性。

getValidator

返回验证者跨执行、共识和快照上下文的完整状态视图。
  • ValExecution(执行视图)
  • 质押和佣金(共识视图)
  • 质押和佣金(快照视图)
函数选择器
函数签名
参数
  1. validatorId - 验证者的 ID
Gas 成本 97,200

getDelegator

返回指定验证者对应的委托者 DelInfo,提供委托者的质押、累积奖励和待生效质押变更的视图。 函数选择器
函数签名
参数
  1. validatorId - 验证者的 ID
  2. delegator - address of the delegator about whose stake we are inquiring
Gas 成本 184,900

getWithdrawalRequest

返回 (validatorId, delegator, withdrawId) 元组对应的待处理 WithdrawalRequest 函数选择器
函数签名
Gas 成本 24,300

get*ValidatorSet

分别返回共识、快照和执行验证者 ID。 函数选择器
函数签名
参数
  1. startIndex - 由于所查找的列表可能非常长,因此这些函数都是分页的,返回所需列表的一个固定长度子集。传入 startIndex 指示从列表的哪个位置开始。
Gas 成本 814,000 gas (assuming PAGINATED_RESULTS_SIZE = 100). 行为 getExecutionValidatorSet() 返回所有符合入选质押标准的完整活跃验证者集合。getSnapshotValidatorSet() 返回被选定为下一纪元领导者的验证者子集。getConsensusValidatorSet() 返回当前纪元中作为领导者的验证者子集。 每次调用从 startIndex 开始最多获取 PAGINATED_RESULTS_SIZE 个验证者 ID,并返回元组 (bool done, uint32 nextIndex, uint256[] valids) bool isDone 表示是否已到达列表末尾。uint32 nextIndex 是数组中的最后一个槽位。

getDelegations

返回给定委托者地址已委托的验证者 ID 的分页列表。 函数选择器
函数签名
参数
  1. delegator - 我们要查询其委托的地址
  2. startValId
Gas 成本 814,000 行为 每次调用从 startValId 开始最多获取 PAGINATED_RESULTS_SIZE 个验证者 ID,并返回元组 (bool isDone, uint64 nextValId, uint64[] valIds),包含来自输入 delegator 地址的委托。 bool isdone 表示是否已到达列表末尾。uint64 nextValIdvalIds 中最后一个元素之后的 ID。将其用作下一次调用的 startValId 如果 delegator 委托的验证者 ID 数超过 PAGINATED_RESULTS_SIZE,则需要多次调用(在 isDone 为 false 时继续)。 要获取完整集合,首次调用请使用 startValId = 0

getDelegators

返回给定验证者的委托者地址分页列表。 函数选择器
函数签名
参数
  1. validatorId - 我们要了解其委托者的验证者的 ID
  2. startDelegator
Gas 成本 814,000 行为 每次调用从 startDelegator 开始最多获取 PAGINATED_RESULTS_SIZE 个委托者地址,并返回元组 (bool isDone, address nextDelegator, address[] delegators),包含对输入 validatorId 的委托。 bool isDone 表示已到达列表末尾。nextDelegatordelegators 中最后一个元素之后的地址。将其用作下一次调用的 startDelegator 要获取完整集合,应使用 startDelegator = 0 调用该函数。
某个验证者的委托者数量可能非常庞大,因此建议通过 events 框架维护一份更新的列表,而不是周期性地调用这个昂贵的查找。

getEpoch

返回当前纪元以及在纪元中的时序(边界区块之前或之后)。 函数选择器
函数签名
Gas 成本 200 行为 如果 inEpochDelayPeriod 为 false,则尚未到达边界区块,此时的写操作应在 epoch + 1 生效。如果 inEpochDelayPeriod 为 true,则网络已过边界区块,此时的写操作应在 epoch + 2 生效

getProposerValId

返回当前区块提议者的验证者 ID,对应于区块作者的 SECP 值。 函数选择器
函数签名
Gas 成本 100

Syscalls

目前有三个 syscall。用户不能直接调用它们。它们只能通过特殊的系统交易触发。

syscallOnEpochChange

在纪元延迟轮次结束时触发,以敲定累加器值并更新纪元状态。 函数选择器
函数签名
参数
  1. epoch - 正要进入的新共识纪元
行为
  1. 如果验证者在上一纪元收到了更改质押的请求,并参与了上一纪元的共识验证者集,则保存相应的累加器值
  2. 如果任何验证者在上一纪元处于活跃状态但在当前纪元变为非活跃,也保存其当前的累加器值
  3. 在状态中设置当前纪元

syscallReward

为每个区块奖励出块的验证者及其委托者已配置的区块奖励。 函数选择器
函数签名
参数
  1. blockAuthor —— 出块验证者的地址。
行为
  1. 如果验证者的佣金不为零,则会将一部分奖励分配给验证者的 authAddress
  2. 剩余的奖励可供验证者的委托者领取。
请注意,佣金按总区块奖励的百分比计算。
  • 假设某验证者的个人质押占其验证者总委托的 20%。
  • 佣金设置为总奖励的 10%。
那么该验证者将获得总区块奖励的 10% 作为佣金。剩余的 90% 分配给质押池。由于该验证者拥有质押池的 20%,他们也将获得剩余部分的 20%。

syscallSnapshot

对当前执行层验证者集进行排序,选出质押最多的前 N 名验证者作为即将到来的共识验证者集,将更新后的集合存入状态,并清除之前的共识集。 函数选择器
函数签名
行为

事件

质押预编译合约会发出出现在交易回执中的标准事件。这些事件为验证者和委托者的操作提供带索引的信息。

ValidatorRewarded

当通过 syscallReward 分配区块奖励,或通过 externalReward 向验证者的质押者发送额外 MON 时发出。

ValidatorCreated

当通过 addValidator 添加验证者时发出。

ValidatorStatusChanged

addValidatordelegateundelegatecompound 期间,当验证者的标志发生变化时发出。

Delegate

当委托金额增加时发出,即在 addValidatordelegatecompound 期间。

Undelegate

当委托者调用 undelegate 时发出。

Withdraw

当委托者成功执行 withdraw 时发出。

ClaimRewards

当委托者通过 claimRewards 领取奖励时发出。

CommissionChanged

当验证者通过 changeCommission 更改佣金时发出。

EpochChanged

当纪元通过 syscallOnEpochChange 改变时发出。

预编译合约内部

验证者结构体

委托者结构体

状态变量

映射

Solidity 质押接口

点击代码块右上角的按钮可复制到剪贴板。

质押 ABI JSON

点击代码块右上角的按钮可复制到剪贴板。

常见问题

没有直接的 removeValidator 函数。相反,如果某验证者的 auth_account 通过 undelegate 移除了足够多的质押,该验证者会在未来某个纪元从共识集合中被移除。这将发生在纪元 n+1 或纪元 n+2,取决于 undelegate 是否发生在纪元延迟轮次内。即使未处于活跃状态,验证者的信息也会始终保留。验证者 ID 是永久的,因为其他委托者可能仍在委托,并需要引用该 val_id 进行解除委托/提现。
验证者可通过调用 changeCommission 更改其 commission
参见 valset getters
参见 getValidator
参见 getDelegator对于该委托者对该验证者的待处理提现,请参见 getWithdrawalRequest
尽管使用了 Solidity 选择器和 ABI,它是一个预编译合约。访问 处的代码会返回空代码。它的账户总是以 warm 方式访问,使用无效参数的调用会消耗全部 gas。例外:如果某账户尝试使用 EIP-7702 将委托设置为质押预编译合约,则对其所有的调用都会回滚。