Hello - great presentation on ERC-1066 at devcon, @expede!
I’d like to propose a group of status codes specifically tailored to token transfers in the 0x5* range (as a pretty significant proportion of transactions deal specifically in that department ). 5 is unused so far, and looks a bit like $ so seems a natural fit to me. Here’s the proposal for that range:
code
description
0x50
transfer failure
0x51
transfer success
0x52
insufficient balance
0x53
insufficient allowance
0x54
invalid sender
0x55
invalid receiver
0x56
invalid operator
0x57
invalid value
0x58
invalid data
0x59
invalid approval
0x5a
invalid state
0x5b
contract paused
0x5c
funds locked
0x5d
invalid issuance
0x5e
invalid redemption
0x5f
token meta or info
0x50 / 0x51 would be for generic success / failure, 0x52 & 0x53 for the most common failure modes in a standard ERC20 token, then 0x54 through 0x58 would signify invalid parameters in more restrictive permissioned tokens. 0x59 would show that the transfer lacks approval (above and beyond the standard allowance), and 0x5a would mean that the transfer would put the token into an impermissible state (for instance, maybe the token restricts the number of holders). 0x5b would signal that all transfers are frozen (maybe the token has been retired or migrated to a new contract) and 0x5c would mean that the particular tokens in question were frozen (e.g. there is a lock-up period for the tokens that is still in effect). 0x5d & 0x5e would be returned if the token transfer would invoke an invalid mint or burn operation, respectively, and 0x5f would signal metadata in the same vein as the rest of the specification.
We’re just back from Prague and in SF for the final weeks of the Tachyon program we are in. @expede is especially slammed because she’s also speaking in New Orleans this week!
Here’s what I propose (in response to our Telegram discussion). I appreciate the depth of error codes you covered here but think a minimal implementation might be the best first step. We can leave slots in the 0x5* range open until they exist or are needed on an organic, case by case basis.
Minimal Subset- checked on canSend()
0x50
transfer failure
0x51
transfer success
0x54
invalid sender
0x55
invalid receiver
0x56
invalid operator (transfer agent)
0x5b
contract paused
0x5c
funds locked (lockup period)
2nd tier- can be checked by front-end instead of in canSend()
0x52
insufficient balance
0x53
insufficient allowance
3rd Tier- implementation yet to be seen
0x57
invalid value
0x58
invalid data
0x59
invalid approval
0x5a
invalid state
0x5d
invalid issuance
0x5e
invalid redemption
0x5f
token meta or info
*Note, I kept the status codes equal to your table above for easier referencing.
5 is unused so far, and looks a bit like $ so seems a natural fit to me.
To me as well The 5 = $ is in fact the visual metaphor that I’m using in my working designs, too. They’re currently in a notebook and on sticky notes on a wall.
but think a minimal implementation might be the best first step
I agree with @pakaplace here. We don’t want to prematurely impose codes, and empty ranges are a feature not a bug. Since these need to keep forward compatibility, a bit of restraint and investment in design early on will go a long way later. It’s only safe to add codes; removing them is problematic since contracts may depend on them.
I do think that there’s value in the codes that @0age proposed; I’d be surprised if these codes need to land in the final design. However, many aren’t specific to finance. For example, “invalid approval” belongs in the authorization column. Since we want consistency for both DX and (autonomous) code efficiency, some of these will need to be laid out differently.
I know that I mentioned this during the Devcon talk, but I truly apologize that ERC1066 v1.1 proposal isn’t up yet Our past few weeks (ie: Devcon and Tachyon) have been B-A-N-A-N-A-S, repeatedly flying intercontinentally, working on last-minute presentations, interviewing companies working with FISSION/ERC1066, possibly getting them on ETC, and so on.
Automerge is also currently broken on the EIPs repo , and we’re waiting for some changes like [restricted] placeholders (ie: @schemar’s suggestion) to be merged.
I’ll try to get a WIP Google Sheet up for everyone to see the current state. I’ll post to FEM when it’s live.
Ok, leaving an empty range for forward-compatibility sounds good to me. I’d say it makes the most sense to rearrange the codes a bit so that 1) the empty range is continuous, and 2) future extensions to the range, if they end up taking the form of the existing suggestions, are in a similar category as those codes at the end of the initial set. The 0x5f code is just keeping with the pattern for the rest of the top-level categories.
code
description
0x50
transfer failure
0x51
transfer success
0x52
insufficient balance
0x53
insufficient allowance
0x54
transfers halted (contract paused)
0x55
funds locked (lockup period)
0x56
invalid sender
0x57
invalid receiver
0x58
invalid operator (transfer agent)
0x59
0x5a
0x5b
0x5a
0x5b
0x5c
0x5d
0x5e
0x5f
token meta or info
Looking forward to discussing further on the 22nd!
“insufficient allowance” vs. “invalid operator” - these are somewhat similar concepts I think, the former more tied to the ERC20 approve / transferFrom and the latter more tied to the ERC777 operator semantics. Could possibly be wrapped up in a single code “invalid operator”.
“funds locked” - I wonder if this could be made a bit more general. Locked funds could be due to vesting, seasoning periods (e.g. 12 month lock up for Reg. D) etc… There are also restrictions at the token level (e.g. maximum number of investors or maximum volume per period). I wonder if distinguishing these two cases (restricted due to sender properties, restricted due to token properties) might be useful?
I’ll def. be dialing into the community call on this - thanks @bmann for organising!
I also feel like 0x59 invalid balance (for representing cases where a minimum or maximum allowed balance would be exceeded) and 0x5a invalid state (for cases where the maximum number of total token holders would be exceeded or other similar errors) are common enough issues to warrant inclusion in the standard.
The past few months have been filled with interviewing around two dozen companies and projects, soliciting general feedback form the community, and exploring alternative code layouts. We had a community call earlier this week, and it’s been great to see the interest both on and beyond Ethereum
One version that seemed promising at first was adding more structure: encoding the referent plus modal & temporal logics. This turned out to be too rigid, so we fell back to using the lowest bit to signify blocking/non-blocking, which is in the current proposal.
Fun Facts
Now have more codes than HTTP
Nearly two dozen projects interviewed for research
Used by at at least three other ERCs (at least one more being announced by a partner soon)
Four FISSION presentations (so far)
Why the major version bump?
As mentioned above, we propose moving a few of the rows to make even numbers “blocking / others have control” and odds “unblocking / you have control”. If there is strong opinion that this should not be the case, it is easily undone.
What’s New?
Columns
0x1* Permission & CONTROL
This column already contained permissions. A prior working design included a column for “stoplight” style transitions. We realized that this is really a type of permission (ie: permission to proceed), and merged it into this column.
Some examples:
0x10 Disallowed or STOP
0x11 Allowed or GO
0x3* Negotiation & GOVERNANCE
Negotiation has been expanded to include decision making and governance, which have lot of overlap.
Some examples:
0x30 Sender Disagreed or NAY
0x31 Sender Agrees or YEA
0x34 Quorum Not Reached
0x4* Availability & Time
Simply expanded to include new rows (see below)
Some examples:
0x42 Paused
0x43 Queued
0x48 Already Complete
Rows
0x*4 Lower Limit
Includes items like:
0x24 Underflow
0x54 Insufficient Funds
0xE4 Untrusted/Unsigned
0x*6 Upper Limit
Includes items like:
0x16 Revoked
0x26 Overflow
0x46 Expired
0x*8 Unnecessary or Duplicate
Includes items like:
0x28 Conflict or Duplicate Entry
0x48 Duplicate Request / Already Complete
0x58 Funds Not Required
Feedback?
We’d love any feedback that the community has before we make a PR against the EIPs repo
We spoke about this on the call, but I wanted to put it in the thread for the broader community.
v1.0.0-beta Code
v1.0.0-beta Description
0age’s Description
0x50
Transfer Failed
transfer failure
0x51
Transfer successful
transfer success
0x54
Insufficient funds
insufficient balance
0x24
Below Ok Range
insufficient allowance
0x42
Paused
transfers halted (contract paused)
0x53
Hold or escrow
funds locked (lockup period)
0x10
Disallowed
invalid sender
0x10
Disallowed
invalid receiver
0x10
Disallowed
invalid operator (transfer agent)
0x5f
Token or financial info
token meta or info
The really challenging ones here are the ones that refer to a specific role in the flow (sender/receiver/operator). I really tried to get these to work with absolute and relative roles, but it doesn’t fit well into the current design philosophy. I’m open to options to get these to work, but here are two rough-but-workable solutions in the meantime:
Use application-specific ranges
Have your protocol or other ERC include rider information:
returns (byte statusCode, address subject)
//...
return (hex"10", msg.sender) // specific operator not okay, taken programatically
return (hex"10", receiverAddress) // specific user not authed
return (hex"10", this) // this contract not authed
This pattern is applicable elsewhere, too
returns (byte statusCode, address subject)
//...
return (hex"26", tokenHolder) // holder has hit the max allowed balance for this token
When a Solidity function returns a boolean, the returned data is padded to an even 32-byte boundary: 0x0000000000000000000000000000000000000000000000000000000000000001.
I presume there was some sort of engineering decision taken by the designers of the RPC to pad the data so drastically. (My guess is that it had something to do with performance. I can’t think of any other reason other than perhaps laziness). Does anyone know why that choice was made?
The reason I’m asking is that this proposal (which inserts a one-byte value at the start of the returned output) may (for all we know) step on that engineering decision. If this proposal takes hold, every previously 32-byte (or 32-byte aligned) return would be off by one byte at the start.
Does anyone know (or has anyone studied) the effect of this, if it becomes widely adopted, on overall system performance or efficiency? (Maybe it kicks something out of some hardware cache, or it causes Solidity compiler to generate horribly inefficient code – no-one knows and that’s the point.)
I recently started this discussion (Small suggested change to EIP 1), in the hopes that EIP authors would try to think about the effect of their proposal system-wide. I’m not sure this EIP does or doesn’t have system-wide effects, but it should be discussed.
Hmm, you’re right to ask I would be very surprised if this caused issues. It’s something that you can do right now, with no changes to the VM. For performance, EVM-native 32-byte numbers typically take more to emulate than single bytes, and thus should (in my WIP EVM implementation at least) be easy to emulate. My best guess about why that happens is that numbers on the stack will are padded to 32-bytes, but don’t know of any concrete reason.
@fubuloubu any ideas? Perhaps you could illuminate how Vyper behaves for bools?
@tjayrush@expede So the reason why it gets encoded as 0x0…1 (len=32) is because of the ABI encoding. Everything on the ABI uses a 32byte boundary - because of the 32byte “stack-word”. Going sub-32 byte gets really inefficient gas wise (in memory, gains are to be had when storing again).
ERC-1066 as I read it is layered on top of the ABI spec. So looking at ERC-1066 spec briefly the abi would return bytes1 which on the binary level is the same as 1 word \ bytes32. So if one wanted on could easily add 31 bytes more of status codes in for the same cost
Ooh, the Finhaven lib is pretty out of date! The current repo has its own GitHub org: Fission · GitHub
On the current version of the helper lib, you have the ability to hand it an #erc-1444 localization directly for the require helpers. Both of these should work today:
// Hardcoded Message
requireOk(someCode, "something went wrong!");
// Using an ERC-1444 automated localization based on the specific code
requireOk(someCode, Localization(0xabcdef));
I’m actively working on getting the singleton language registry set up, which can then get hardcoded into the lib. The above would then look like: