ERC-1066: 状态码
Authors | Brooklyn Zelenka (@expede), Tom Carchrae (@carchrae), Gleb Naumenko (@naumenkogs) |
---|---|
Created | 2018-05-05 |
Discussion Link | https://ethereum-magicians.org/t/erc-1066-ethereum-status-codes-esc/ |
简单总结
广泛适用于智能合约的状态码。
摘要
本标准概述了一组类似于 HTTP 状态的通用状态码。这提供了一组共享的信号,允许智能合约自主地对情况做出反应,向用户公开本地化的错误消息等等。
目前最先进的做法是,除了明确的成功之外,对任何事情都进行 revert
(即:需要人为干预),或者返回一个低上下文的 true
或 false
。状态码与使用原因进行 revert
在相似但正交,但目标是自动化、调试和最终用户反馈(包括翻译)。它们与 revert
和使用原因进行 revert
完全兼容。
与 HTTP 的情况一样,拥有一组已知的标准代码对开发人员有很多好处。它们消除了为每个合约开发自己的方案的需求带来的摩擦,使合约间的自动化更容易,并且更容易广泛地理解你的请求产生了哪些有限状态。重要的是,它使得区分预期错误状态、需要停止执行的真正异常情况、正常状态转换和各种成功案例变得更加容易。
动机
语义密度
HTTP 状态码被广泛用于此目的。BEAM 语言使用原子和带标签的元组来表示几乎相同的信息。两者都为程序员(例如调试)和需要决定下一步做什么的程序提供了大量信息。
状态码传递的信息比 布尔值 丰富得多,并且能够像任意字符串一样自主地做出反应。
用户体验 (UX)
最终用户几乎没有得到任何反馈,并且没有翻译层。
由于 ERC1066 状态码是有限的并且是预先知道的,我们可以利用 ERC-1444 来提供全局的、人类可读的状态消息集。这些也可以翻译成任何语言,不同级别的技术细节,添加为 revert
消息,natspecs 等等。
状态码传递的信息比布尔值丰富得多,并且能够像任意字符串一样自主地做出反应。
开发者体验 (DX)
开发者目前几乎没有智能合约公开的上下文。
在撰写本文时,除了逐步执行 EVM 执行并直接检查内存转储之外,很难理解智能合约执行期间发生了什么。通过返回更多上下文,开发人员可以编写分解良好的测试,并断言返回某些代码,以表达智能合约到达的位置。这包括作为裸值的状态码、event
和 revert
。
拥有一组固定的代码也使得编写通用辅助函数以对某些信号做出常见反应成为可能。这可以存在于链下或链上的库中,从而降低了构建智能合约的开销,并通过受信任的共享组件帮助提高代码质量。
我们还在 交易中 发现了对此的需求,并且没有理由 EVM 本身不能使用这些状态码。
智能合约自治
智能合约对请求结果的了解很少,除了通过/失败;它们可以通过更多上下文变得更智能。
智能合约很大程度上是为了实现自治。虽然每个合约都可以定义一个特定的接口,但拥有一组通用的语义代码可以帮助开发人员编写能够对各种情况做出适当反应的代码。
虽然显然相关,但状态码是对带有原因的 revert
的补充。状态码不限于回滚交易,并且可能表示已知的错误状态而无需停止执行。它们还可以表示链下条件,提供一个字符串来 revert,发出时间延迟信号等等。
所有这些使得合约可以共享状态转换、结果和内部更改的通用词汇表,而无需深入理解自定义状态枚举或协作合约的内部业务逻辑。
规范
格式
代码可以单独返回,也可以作为多个返回值的第一个值返回。
// 仅状态
function isInt(uint num) public pure returns (byte status) {
return hex"01";
}
// 状态和值
uint8 private counter;
function safeIncrement(uint8 interval) public returns (byte status, uint8 newCounter) {
uint8 updated = counter + interval;
if (updated >= counter) {
counter = updated;
return (hex"01", updated);
} else {
return (hex"00", counter);
}
}
代码表
代码可以很好地分解成一个 16x16 的矩阵,表示为一个 2 位十六进制数。高位表示代码的种类或“类别”,低位包含状态或“原因”。为了便于解释和布局,我们在下面将它们表示为每个范围的单独表格。
注意:未指定的代码_不能_随意使用,而是开放供进一步指定。
0x0*
通用
通用代码。这些代码兼作裸“原因”,因为 0x01 == 1
。
代码 | 描述 |
---|---|
0x00 |
失败 |
0x01 |
成功 |
0x02 |
等待他人操作 |
0x03 |
已接受 |
0x04 |
下限或不足 |
0x05 |
请求接收方操作 |
0x06 |
上限 |
0x07 |
[保留] |
0x08 |
重复、不必要或不适用 |
0x09 |
[保留] |
0x0A |
[保留] |
0x0B |
[保留] |
0x0C |
[保留] |
0x0D |
[保留] |
0x0E |
[保留] |
0x0F |
信息性或元数据 |
0x1*
权限与控制
也用于常见的状态机操作(例如“红绿灯”操作)。
代码 | 描述 |
---|---|
0x10 |
不允许或停止 |
0x11 |
允许或继续 |
0x12 |
等待他人的许可 |
0x13 |
已请求许可 |
0x14 |
太开放/不安全 |
0x15 |
需要你的许可或继续请求 |
0x16 |
已撤销或已禁止 |
0x17 |
[保留] |
0x18 |
不适用于当前状态 |
0x19 |
[保留] |
0x1A |
[保留] |
0x1B |
[保留] |
0x1C |
[保留] |
0x1D |
[保留] |
0x1E |
[保留] |
0x1F |
权限详细信息或控制条件 |
0x2*
查找、不等式与范围
此范围广泛用于查找和匹配。数据查找和订单匹配是两个常见的用例。
代码 | 描述 |
---|---|
0x20 |
未找到、不相等或超出范围 |
0x21 |
已找到、相等或在范围内 |
0x22 |
等待匹配 |
0x23 |
已发送匹配请求 |
0x24 |
低于范围或下溢 |
0x25 |
匹配请求 |
0x26 |
高于范围或溢出 |
0x27 |
[保留] |
0x28 |
重复、冲突或碰撞 |
0x29 |
[保留] |
0x2A |
[保留] |
0x2B |
[保留] |
0x2C |
[保留] |
0x2D |
[保留] |
0x2E |
[保留] |
0x2F |
匹配元数据或信息 |
0x3*
协商与治理
协商,以及非常广泛的此类交易流程。请注意,“另一方”可能不止一个参与者(不一定是发送方)。
代码 | 描述 |
---|---|
0x30 |
发送方不同意或否决 |
0x31 |
发送方同意或赞成 |
0x32 |
等待批准 |
0x33 |
已发送报价或已投票 |
0x34 |
未达到法定人数 |
0x35 |
请求接收方批准 |
0x36 |
已达到报价或投票限制 |
0x37 |
[保留] |
0x38 |
已经投票 |
0x39 |
[保留] |
0x3A |
[保留] |
0x3B |
[保留] |
0x3C |
[保留] |
0x3D |
[保留] |
0x3E |
[保留] |
0x3F |
协商规则或参与信息 |
0x4*
可用性与时间
服务或操作可用性。
代码 | 描述 |
---|---|
0x40 |
不可用 |
0x41 |
可用 |
0x42 |
已暂停 |
0x43 |
已加入队列 |
0x44 |
尚未可用 |
0x45 |
等待你的可用性 |
0x46 |
已过期 |
0x47 |
[保留] |
0x48 |
已完成 |
0x49 |
[保留] |
0x4A |
[保留] |
0x4B |
[保留] |
0x4C |
[保留] |
0x4D |
[保留] |
0x4E |
[保留] |
0x4F |
可用性规则或信息(例如,自…以来或直到…的时间) |
0x5*
代币、资金与金融
特殊代币和金融概念。许多相关概念包含在其他范围中。
代码 | 描述 |
---|---|
0x50 |
转账失败 |
0x51 |
转账成功 |
0x52 |
等待他人付款 |
0x53 |
扣留或托管 |
0x54 |
资金不足 |
0x55 |
已请求资金 |
0x56 |
超过转账量 |
0x57 |
[保留] |
0x58 |
不需要资金 |
0x59 |
[保留] |
0x5A |
[保留] |
0x5B |
[保留] |
0x5C |
[保留] |
0x5D |
[保留] |
0x5E |
[保留] |
0x5F |
代币或金融信息 |
0x6*
待定
目前未指定。(完整范围保留)
0x7*
待定
目前未指定。(完整范围保留)
0x8*
待定
目前未指定。(完整范围保留)
0x9*
待定
目前未指定。(完整范围保留)
0xA*
应用程序特定代码
合约可能具有它们需要发出信号的特殊状态。本提案仅概述了最广泛的含义,但实现者可能对每个状态码都有非常具体的含义,只要它们与更广泛的定义一致。
代码 | 描述 |
---|---|
0xA0 |
应用程序特定失败 |
0xA1 |
应用程序特定成功 |
0xA2 |
应用程序特定等待他人操作 |
0xA3 |
应用程序特定接受 |
0xA4 |
应用程序特定低于条件 |
0xA5 |
应用程序特定请求接收方操作 |
0xA6 |
应用程序特定过期或限制 |
0xA7 |
[保留] |
0xA8 |
应用程序特定不适用条件 |
0xA9 |
[保留] |
0xAA |
[保留] |
0xAB |
[保留] |
0xAC |
[保留] |
0xAD |
[保留] |
0xAE |
[保留] |
0xAF |
应用程序特定元数据或信息 |
0xB*
待定
目前未指定。(完整范围保留)
0xC*
待定
目前未指定。(完整范围保留)
0xD*
待定
目前未指定。(完整范围保留)
0xE*
加密、身份与证明
围绕签名、密码学、签名和应用程序级别身份验证的操作。
元代码 0xEF
通常用于发出描述所用算法或过程的有效负载信号。
代码 | 描述 |
---|---|
0xE0 |
解密失败 |
0xE1 |
解密成功 |
0xE2 |
等待其他签名或密钥 |
0xE3 |
已签名 |
0xE4 |
未签名或不受信任 |
0xE5 |
需要签名 |
0xE6 |
已知被泄露 |
0xE7 |
[保留] |
0xE8 |
已签名或未加密 |
0xE9 |
[保留] |
0xEA |
[保留] |
0xEB |
[保留] |
0xEC |
[保留] |
0xED |
[保留] |
0xEE |
[保留] |
0xEF |
密码学、ID 或证明元数据 |
0xF*
链下
用于链下操作。与 0x0*: 通用
范围非常相似,0xF*
非常通用,并且几乎不修改原因。
除其他事项外,元代码 0xFF
可用于描述链下过程是什么。
代码 | 描述 |
---|---|
0xF0 |
链下失败 |
0xF1 |
链下成功 |
0xF2 |
等待链下过程 |
0xF3 |
链下过程已启动 |
0xF4 |
链下服务无法访问 |
0xF5 |
需要链下操作 |
0xF6 |
链下过期或达到限制 |
0xF7 |
[保留] |
0xF8 |
重复的链下请求 |
0xF9 |
[保留] |
0xFA |
[保留] |
0xFB |
[保留] |
0xFC |
[保留] |
0xFD |
[保留] |
0xFE |
[保留] |
0xFF |
链下信息或元数据 |
作为表格
0x0* 通用 |
0x1* 权限与控制 |
0x2* 查找、不等式与范围 |
0x3* 协商与治理 |
0x4* 可用性与时间 |
0x5* 代币,资金与金融 |
0x6* 待定 |
0x7* 待定 |
0x8* 待定 |
0x9* 待定 |
0xA* 应用程序特定代码 |
0xB* 待定 |
0xC* 待定 |
0xD* 待定 |
0xE* 加密,身份与证明 |
0xF* 链下 |
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x*0 |
0x00 失败 |
0x10 不允许或停止 |
0x20 未找到,不相等或超出范围 |
0x30 发送方不同意或否决 |
0x40 不可用 |
0x50 转账失败 |
0x60 [保留] |
0x70 [保留] |
0x80 [保留] |
0x90 [保留] |
0xA0 应用程序特定失败 |
0xB0 [保留] |
0xC0 [保留] |
0xD0 [保留] |
0xE0 解密失败 |
0xF0 链下失败 |
0x*1 |
0x01 成功 |
0x11 允许或继续 |
0x21 已找到,相等或在范围内 |
0x31 发送方同意或赞成 |
0x41 可用 |
0x51 转账成功 |
0x61 [保留] |
0x71 [保留] |
0x81 [保留] |
0x91 [保留] |
0xA1 应用程序特定成功 |
0xB1 [保留] |
0xC1 [保留] |
0xD1 [保留] |
0xE1 解密成功 |
0xF1 链下成功 |
0x*2 |
0x02 等待他人操作 |
0x12 等待他人的许可 |
0x22 等待匹配 |
0x32 等待批准 |
0x42 已暂停 |
0x52 等待他人付款 |
0x62 [保留] |
0x72 [保留] |
0x82 [保留] |
0x92 [保留] |
0xA2 应用程序特定等待他人操作 |
0xB2 [保留] |
0xC2 [保留] |
0xD2 [保留] |
0xE2 等待其他签名或密钥 |
0xF2 等待链下过程 |
0x*3 |
0x03 已接受 |
0x13 已请求许可 |
0x23 已发送匹配请求 |
0x33 已发送报价或已投票 |
0x43 已加入队列 |
0x53 扣留或托管 |
0x63 [保留] |
0x73 [保留] |
0x83 [保留] |
0x93 [保留] |
0xA3 应用程序特定接受 |
0xB3 [保留] |
0xC3 [保留] |
0xD3 [保留] |
0xE3 已签名 |
0xF3 链下过程已启动 |
0x*4 |
0x04 下限或不足 |
0x14 太开放/不安全 |
0x24 低于范围或下溢 |
0x34 未达到法定人数 |
0x44 尚未可用 |
0x54 资金不足 |
0x64 [保留] |
0x74 [保留] |
0x84 [保留] |
0x94 [保留] |
0xA4 应用程序特定低于条件 |
0xB4 [保留] |
0xC4 [保留] |
0xD4 [保留] |
0xE4 未签名或不受信任 |
0xF4 链下服务无法访问 |
0x*5 |
0x05 请求接收方操作 |
0x15 需要你的许可或继续请求 |
0x25 匹配请求 |
0x35 请求接收方批准 |
0x45 等待你的可用性 |
0x55 已请求资金 |
0x65 [保留] |
0x75 [保留] |
0x85 [保留] |
0x95 [保留] |
0xA5 应用程序特定请求接收方操作 |
0xB5 [保留] |
0xC5 [保留] |
0xD5 [保留] |
0xE5 需要签名 |
0xF5 需要链下操作 |
0x*6 |
0x06 上限 |
0x16 已撤销或已禁止 |
0x26 高于范围或溢出 |
0x36 已达到报价或投票限制 |
0x46 已过期 |
0x56 超过转账量 |
0x66 [保留] |
0x76 [保留] |
0x86 [保留] |
0x96 [保留] |
0xA6 应用程序特定过期或限制 |
0xB6 [保留] |
0xC6 [保留] |
0xD6 [保留] |
0xE6 已知被泄露 |
0xF6 链下过期或达到限制 |
0x*7 |
0x07 [保留] |
0x17 [保留] |
0x27 [保留] |
0x37 [保留] |
0x47 [保留] |
0x57 [保留] |
0x67 [保留] |
0x77 [保留] |
0x87 [保留] |
0x97 [保留] |
0xA7 [保留] |
0xB7 [保留] |
0xC7 [保留] |
0xD7 [保留] |
0xE7 [保留] |
0xF7 [保留] |
0x*8 |
0x08 重复、不必要或不适用 |
0x18 不适用于当前状态 |
0x28 重复,冲突或碰撞 |
0x38 已经投票 |
0x48 已完成 |
0x58 不需要资金 |
0x68 [保留] |
0x78 [保留] |
0x88 [保留] |
0x98 [保留] |
0xA8 应用程序特定不适用条件 |
0xB8 [保留] |
0xC8 [保留] |
0xD8 [保留] |
0xE8 已签名或未加密 |
0xF8 重复的链下请求 |
0x*9 |
0x09 [保留] |
0x19 [保留] |
0x29 [保留] |
0x39 [保留] |
0x49 [保留] |
0x59 [保留] |
0x69 [保留] |
0x79 [保留] |
0x89 [保留] |
0x99 [保留] |
0xA9 [保留] |
0xB9 [保留] |
0xC9 [保留] |
0xD9 [保留] |
0xE9 [保留] |
0xF9 [保留] |
0x*A |
0x0A [保留] |
0x1A [保留] |
0x2A [保留] |
0x3A [保留] |
0x4A [保留] |
0x5A [保留] |
0x6A [保留] |
0x7A [保留] |
0x8A [保留] |
0x9A [保留] |
0xAA [保留] |
0xBA [保留] |
0xCA [保留] |
0xDA [保留] |
0xEA [保留] |
0xFA [保留] |
0x*B |
0x0B [保留] |
0x1B [保留] |
0x2B [保留] |
0x3B [保留] |
0x4B [保留] |
0x5B [保留] |
0x6B [保留] |
0x7B [保留] |
0x8B [保留] |
0x9B [保留] |
0xAB [保留] |
0xBB [保留] |
0xCB [保留] |
0xDB [保留] |
0xEB [保留] |
0xFB [保留] |
0x*C |
0x0C [保留] |
0x1C [保留] |
0x2C [保留] |
0x3C [保留] |
0x4C [保留] |
0x5C [保留] |
0x6C [保留] |
0x7C [保留] |
0x8C [保留] |
0x9C [保留] |
0xAC [保留] |
0xBC [保留] |
0xCC [保留] |
0xDC [保留] |
0xEC [保留] |
0xFC [保留] |
0x*D |
0x0D [保留] |
0x1D [保留] |
0x2D [保留] |
0x3D [保留] |
0x4D [保留] |
0x5D [保留] |
0x6D [保留] |
0x7D [保留] |
0x8D [保留] |
0x9D [保留] |
0xAD [保留] |
0xBD [保留] |
0xCD [保留] |
0xDD [保留] |
0xED [保留] |
0xFD [保留] |
0x*E |
0x0E [保留] |
0x1E [保留] |
0x2E [保留] |
0x3E [保留] |
0x4E [保留] |
0x5E [保留] |
0x6E [保留] |
0x7E [保留] |
0x8E [保留] |
0x9E [保留] |
0xAE [保留] |
0xBE [保留] |
0xCE [保留] |
0xDE [保留] |
0xEE [保留] |
0xFE [保留] |
0x*F |
0x0F Informational or Metadata |
0x1F Permission Details or Control Conditions |
0x2F Matching Meta or Info |
0x3F Negotiation Rules or Participation Info |
0x4F Availability Rules or Info (ex. time since or until) |
0x5F Token or Financial Information |
0x6F [保留] |
0x7F [保留] |
0x8F [保留] |
0x9F [保留] |
0xAF App-Specific Meta or Info |
0xBF [保留] |
0xCF [保留] |
0xDF [保留] |
0xEF Cryptography, ID, or Proof Metadata |
0xFF Off-Chain Info or Meta |
示例函数更改
uint256 private startTime;
mapping(address => uint) private counters;
// 之前
function increase() public returns (bool _available) {
if (now < startTime && counters[msg.sender] == 0) {
return false;
};
counters[msg.sender] += 1;
return true;
}
// 之后
function increase() public returns (byte _status) {
if (now < start) { return hex"44"; } // 尚未提供
if (counters[msg.sender] == 0) { return hex"10"; } // 未经授权
counters[msg.sender] += 1;
return hex"01"; // 成功
}
示例序列图
0x03 = 等待中
0x31 = 另一方(即:不是你)同意
0x41 = 可用
0x44 = 尚未可用
交易所
AwesomeCoin DEX 交易机器人
+ + +
| | buy(AwesomeCoin) |
| | <------------------------+
| buy() | |
| <---------------------+ |
| | |
| 状态 [0x44] | |
+---------------------> | 状态 [0x44] |
| +------------------------> |
| | |
| | isDoneYet() |
| | <------------------------+
| | |
| | 状态 [0x44] |
| +------------------------> |
| | |
| | |
| 状态 [0x41] | |
+---------------------> | |
| | |
| buy() | |
| <---------------------+ |
| | |
| | |
| 状态 [0x31] | |
+---------------------> | 状态 [0x31] |
| +------------------------> |
| | |
| | |
| | |
| | |
+ + +
0x01 = 通用成功
0x10 = 禁止
0x11 = 允许
代币验证
买方 受监管代币 代币验证器 ID Checker 支出限制器
+ + + + +
| buy() | | | |
+------------------------> | check() | | |
| +-----------------------> | check() | |
| | +-----------------------> | |
| | | | |
| | | 状态 [0x10] | |
| | 状态 [0x10] | <-----------------------+ |
| revert() | <-----------------------+ | |
| <------------------------+ | | |
| | | | |
+---------------------------+ | | | |
| | | | | |
| 使用提供程序更新 ID | | | | |
| | | | | |
+---------------------------+ | | | |
| | | | |
| buy() | | | |
+------------------------> | check() | | |
| +-----------------------> | check() | |
| | +-----------------------> | |
| | | | |
| | | 状态 [0x11] | |
| | | <-----------------------+ |
| | | | |
| | | | check() |
| | +-------------------------------------------> |
| | | | |
| | | | 状态 [0x11] |
| | 状态将多个 code 打包到一个 `bytes32` 中,理论上很美好,但会带来额外的挑战。未使用的空间可能被解释为 `0x00 Failure`,你只能有效地一次打包四个 code,并且确保 code 组合有意义存在挑战。强制将四个 code 打包成一种表示形式,会鼓励返回多个状态 code,但这通常比严格意义上需要的更多信息。这可能导致自相矛盾的结果(例如 `0x00` 和 `0x01` 一起出现),或者将更多的资源分配给解释 256<sup>4</sup>(43 亿)种排列组合。
### 多重返回
虽然在某些情况下,打包状态 code 的字节数组可能是有意义的,但最简单、最具前向兼容性的传输方法是作为多重返回的第一个值。
熟悉也是一个驱动因素。一致的位置和编码共同遵循了最小惊讶原则。它既可以看作是 HTTP 类比中的“头部”,也可以看作是 BEAM 标记元组中的“标签”。
### 人工可读
开发者不应该被要求记住 256 个 code。然而,它们可以很好地分解成一个表格。通过将表格组织成类别和原因,可以降低认知负荷。`0x10` 和 `0x11` 属于同一类别,`0x04` 与 `0x24` 有共同的原因。
虽然这个仓库包含了辅助枚举,但我们发现直接使用十六进制值非常自然。例如,状态 code `0x10` 就像 HTTP 401 一样令人感到舒服。
#### 本地化
这个规范中一个常见的需求是 code 的人工可读翻译。这已被移至其自身的提案:[ERC-1444](/docs/eips/EIPS/eip-1444/),主要是因为希望保持两个规范的重点。
### 扩展性
`0xA` 类别是为应用程序特定的状态保留的。如果 256 个 code 不够用,则可以将 `bytes1` 嵌入到更大的字节数组中。
### EVM Codes
EVM 还在交易中返回一个状态 code;具体来说是 `0x00` 和 `0x01`。该提案既符合这两个 code 的含义,也可以稍后在 EVM 层面使用。
### 空白空间
就像 HTTP 状态 code 有大量未使用的范围一样,本提案中也有完全空白的部分。目的是不预先强制使用一套完整的 code,并允许用户随着时间的推移建议这些空间的使用方式。
### 超越错误
本规范旨在远不止是一组常见的错误。一个设计目标是支持更轻松的合约间通信、基于状态 code 构建的协议以及跨链流程。这些情况中的许多包括预期类型的异常状态(与真正的错误相反)、中性状态、时间逻辑和各种成功。
正如 HTTP 200 与 HTTP 201 的含义不同一样,ERC-1066 状态 code 可以在合约之间传递信息,而不仅仅是传递通过或失败。它们可以被认为是图中智能合约作为节点的边。
### 完全可 `revert`
_本规范与带有原因的 `revert` 完全兼容,并且不打算以任何方式取代它。_ 通过使用通用 code 进行 revert,开发人员可以从一组已知的错误状态中确定哪里出了问题。
此外,通过结合利用 ERC-1066 和翻译表(例如 ERC-1444),开发人员和最终用户都可以收到他们选择的语言和措辞的全自动人工可读错误消息。
### 半字节顺序
半字节顺序对机器没有影响,纯粹是助记符。最初,这个设计是相反的顺序,但为了方便性而进行了更改。由于它与 HTTP 的方案不同,因此最初可能会感到奇怪,但在使用几个小时后会变得非常自然。
#### 简短形式
通用的是 `0x0*`,通用 code 与其整数表示形式一致
```solidity
hex"1" == hex"01" == 1 // with casting
合约类别
许多应用程序将始终是同一类别的一部分。例如,验证通常在 0x10
范围内。
contract Whitelist {
mapping(address => bool) private whitelist;
uint256 private deadline;
byte constant private prefix = hex"10";
check(address _, address _user) returns (byte _status) {
if (now >= deadline) { return prefix | 5; }
if (whitelist[_user]) { return prefix | 1; }
return prefix;
}
}
助手
以上也意味着使用应用程序特定的枚举会稍微容易一些,并且还可以节省 gas(所需的操作更少)。
enum Sleep {
Awake,
Asleep,
BedOccupied,
WindingDown
}
// From the helper library
// 来自辅助库
function appCode(Sleep _state) returns (byte code) {
return byte(160 + _state); // 160 = 0xA0
}
// Versus
// 相比之下
function appCode(Sleep _state) returns (byte code) {
return byte((16 * _state) + 10); // 10 = 0xA
}
实施
参考案例和辅助库(Solidity 和 JS)可以在以下位置找到:
版权
通过 CC0 放弃版权和相关权利。
Citation
Please cite this document as:
Brooklyn Zelenka (@expede), Tom Carchrae (@carchrae), Gleb Naumenko (@naumenkogs), "ERC-1066: 状态码 [DRAFT]," Ethereum Improvement Proposals, no. 1066, May 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1066.