EIP-2069: Recommendation for using YAML ABI in specifications

Discussion URL for


I find this a very interesting idea.

It would be excellent if I could scrape the EIP repo and easily parsed standards. I build tools that benefit immeasurably from the standards. I could support them all (or any portion I wish) if the process was more easily automated.

Why not even go further and automate the process to scrape the EIP repo looking for these finalized standards and lay them down into some immutable file store? Finalized EIPs are supposed to never change. We should store them (in machine readable format) at a hash and add the hash to the repo.

1 Like

Isn’t YAML a superset of JSON? Couldn’t we just do this?

The EIP/ERC explains this and the motivation. YAML is a superset, but if we use the JSON-compatible features, then we get the benefit of in-line comments, perhaps more readable structure and that the YAML spec can be converted to the JSON undrestood by tools.

Hmm, this seems to be of primary benefit to situations where the json is not automatically generated, but human managed or created. Things like test cases and external interfaces come to mind. Perhaps extending this spec to cover some of the common test case formats would be of value? This spec could also be used when testing tools that work with ABIs in test cases for those tools.

Here are some of my ABI test cases, based on the ethers.js/tests/tests/ contract-interface-abi2.json.gz test case format (minus the solidity-specific properties): https://github.com/esaulpaugh/headlong/blob/master/src/test/resources/tests/headlong/tests/abi_tests.json

The whole point of the proposal is to move on from Solidity interfaces to defining interfaces as YAML. This would reduce the dependency on Solidity.

I guess it could be, but I’m not sure.

I didn’t make that connection before, although it is spelled out plainly. This is definitely a benefit, but not necessarily solving all the problems other languages have with the current way ERC specifications are made.

For example, many people lately have been defining ERCs with the heavy use of dynamic arrays arguments, a feature Vyper doesn’t currently support (but we are working on it). My hope would be that people would define single-size arguments in their interfaces, but people make use of more advanced features like this pretty pervasively. And even more generally, the use of mixedCamelCase in defining the names of everything has forced us to adopt that style over the more Pythonic snake_case style that Python linting tools expect.

Not that we should (or can) remove these choices that derived originally from the use of the Solidity language in defining many early ERCs, but there are many more subtle decisions made which cannot be resolved by creating a more generic specification format, although I do welcome the intent behind doing that.

Another thing that comes to mind is the EIP190/1123 ethPM packaging format, which leverages JSON, and people will occasionally use to define packages manually for testing purposes, etc.

Actually on that note the other benefit would be that only features included in the Contract ABI can be specified and Solidity specific features cannot. However, dynamic arrays are “part of the Contract ABI” as long as we consider the spec in the Solidity documentation the canonical one. Unless this one is merged https://github.com/ethereum/EIPs/pull/1605 (we’ve actually discussed and hope to finalise and merge it next week)

That one should definitely be merged. Perhaps the Solidity examples in that spec could be JSON/YAML ones instead?

I agree this is a very good reason why this proposal will help improve the formulation of ERCs.

As they should be. I wasn’t advocating for changing that part of the ABI spec, more thinking it would be good guidance for the construction of ERCs not to use dynamic arrays by default. It complicates the implementation’s handling of the ERC, and uses a newer feature that IIRC is only available with ABIEncoderV2 in Solidity.

Change the format slightly to support “interface” names:

# The transfer function. Takes the recipient address
# as an input and returns a boolean signaling the result.
- name: transfer
  type: function
  stateMutability: nonpayable
  - name: recipient
    type: address
  - name: amount
    type: uint256
  - name: ''
    type: bool
- name: balance
  type: function

- name: transfer
  type: function
- name: balance
  type: function

Also created a dumb Javascript tool to convert that into a Solidity interface: https://github.com/axic/yamabi

It translates the above to:

interface ERC20 {
  function transfer(address recipient, uint256 amount)  returns (bool);
  function balance();

interface ERC2020 {
  function transfer();
  function balance();
1 Like