EIP-4804: Web3 URL to EVM Call Message Translation

Thank you for your answers!

Ok, yes the usecase I had in mind was, what if I want to directly access the value because I am using for example <img src="web3://..." />,…
But yes this usecase should be very very rare, and if it happens, one can always write a method proxying this. So I drop this.

Ok so if I understand correctly, in your example, the actual web3 url would be : web3://0x804a6b66b071e7e6494ae0e03768a536ded64262/compose/string!111.svg
I can see a problem : Let’s take
web3://0xxxxxx/method/string!bla.svg
What if I wanted to send the string “bla.svg” as argument to the method? So here I don’t want to cast the result as SVG, I just want to send the string “bla.svg”.
So if a method ask for a string, and by bad luck, there is at the end of the string a dot and some letters, and the browser recognized these letters as a mime type, then the browser would remove the dot and the letters from the argument given to the method, and the browser would wrongly cast the output as something not planned.
Maybe an idea would be to put the (still optional) mime suffix to the method, web3://<contract>/<method>[.<suffix>]/<arg1>... such as web3://0xxxxxx/method.html/string!bla.svg ?

Ok for mime type.
Regarding the return data types, is it mandatory on the manual mode that a method must return only one value, or can it returns multiple values, and we have to declare it with returns=() ?

Thank you for your answers :slight_smile:

Thanks for the comments. If the string happens to be the last argument with a suffix, it may return an undesired MIME. However, I would guess such a situation will be rare for auto mode. In the manual mode, since the contract developer already knows EIP-4804, the MIME with the last argument with a suffix should fall into the contract design expectation (i.e., the developer should avoid passing “.svg” as the last argument to a non-svg data).

The key thing is that the auto mode is designed to be compatible with existing contracts, which are not aware of EIP-4804, and thus we should not rely on any assumption on the method name. If the contract uses manual mode, then the contract developer should be aware of EIP-4804, and thus the developer could design the way to work with MIME detection correctly. What do you think?

In the long term, we may add the third mode (or an option to manual mode) to support the MIME return by contracts. That means each contract method in this method will return (bytes32, bytes32), where the first one is the MIME type, and the second one is the data. Or we may even support a mode that each method will return (httpResponseHeader, bytes32). However, this seems to be a rather big change, we need to collect more comments from the community, especially experts from HTTP or browsers.

Thanks for the comment. The manual mode is designed for the contracts designed for the frontend, so it only returns one value (bytes32) and declares it with returns=() will just pass the data to calldata.

In the future, we may add the reserved queries that may be prefixed by __ (double underscore) if we want to pass more other info such as gasLimit, but we may need to collect more consensus from the community to see if it is the best way.

Thank for the answer.

Ok for auto mode : we can say that when we develop a website, and we want to call a external third-party method that could trigger this bug, we can write a wrapper around it.
So I will focus on manual mode :

I think it is too bad that, when I develop an onchain website, I will always need to think that there should be not dots in the last argument of my URLs.

My string arguments would either need to not be the last argument of URLs, or need to not contains dots. If the string is provided by user, I would need to replace dots by another placeholder.
And I just realized that even float numbers have this issue :

web3://xxxx/method_using_gps_coordinautes/36.214/23.123

(unfortunately “.123” is a valid mime type of application/vnd.lotus-1-2-3)
So if I want to make a method that takes as input only a float, I would need to add a dummy argument at the end, or replace dots by a placeholder, or scale them by 10^n to avoid the dot.

Would it not be better to do it in a way that does not add constraints on the contents of your arguments when you develop a onchain website?

If you think it is not a problem, I will say no more and I will implement the browser using the current EIP-4804 definition.

That’s great to hear :slight_smile: I also have some ideas for a third mode, but yeah let’s keep that for later.

Thanks for the comment. With the float or with dots in argument, I think an easy is to add the suffix to tell what type it is. E.g., for web3://xxxx/method_using_gps_coordinautes/36.214/23.123, if you want to return an SVG file, then you can have the URL as

web3://xxxx/method_using_gps_coordinautes/36.214/23.123.svg

This will allow the system to quickly identify the MIME to return.

Note that, in manual mode, we may not expect to have method in the path (while auto mode will always have) since all path+query will be sent to the contract as the calldata. Taking Vitalik’s blog as an example, the following is a valid web3:// URL

web3://vitalikblog.eth/index.html

where index.html is just the path of the file (i.e., calldata=‘/index.hml’).

Hope this could explain. Thank you!

Thanks for the reply!
Ok got it: if there is the possibility of a dot in the last argument, always add the extension.
I will now work to implement web3:// on the evm-browser.

1 Like

I think I should post it here too :
Here is an proof of concept implementation of eip-4804, with support of proposed EIP-6821 for domain name resolution:

Only limitation : web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies) are disabled (very indirectly due to chromium URL parser not liking hexadecimal numbers as a host of an URL)

1 Like

Fantastic work! Looking forward to the full support!

ERC-4804: Web3 URL to EVM Call Message Translation with @qizhou

2 Likes

Many thanks for organizing and hosting the interview!

1 Like

I’m happy to have found this EIP; it’s an idea I was thinking should be created, and glad to see that it’s had great progress made!

As an artist and developer, I’m keenly interested in the image/SVG handling. Sounds like handling of URLs ending in .svg is in progress but not quite implemented yet? From my experience exploring existing smart contracts that do on-chain image-generation, for string or bytes returns, there’s a few ways they format the results:

The “Raw String” style would need a suffix on it in the Web3 URL, or would have to use some form of “magic bytes” processing to guess at the file format (which would likely have varying levels of success being automatic). Data-URL-formatted strings could be automatically unwound by the gateway server and have a good level of confidence in what format the output is supposed to be (for standard mediatypes). This would help many different output types, including text formats (e.g. Autoglyphs web3://0xd4e4078ca3495de5b1d4db434bebc5a986197782/draw/100)

The “Token URI” format is a special case that I’m not sure if the Web3 URL gateway wants to be able to support? In general it’s a question of if the gateway structure wants to be able to unwind JSON-structured results programmatically? If the request ends in “/100.json”, it’s clear the request is desiring JSON as a response. But if the request ends with “/100.svg”, but the smart contract returns a string that has a data URL prefix indicating it’s JSON, the gateway could parse the JSON, and return just the image property of the JSON object?

Or, to be more specific, the Web3 URL format could create a specific way to indicate a specific property of a JSON result is desired? Some possible URL formats for “sending argument ‘100’ results in a string output that is JSON-encoded. Grab the ‘image’ property of that JSON object and return it, formatted as an SVG”:

  • .../100.json/image.svg
  • .../100.json#image.svg
  • .../100.json?result=(image:image/svg+xml)

That first format treats JSON files as if they were folders in a file hierarchy, which seems to fit with the other goals of this initiative?

One other thing to consider is using the Accept HTTP header as a way to deduce the request’s intent, and also as a way to determine desired failback methods. A request that comes with a header of

Accept: image/svg+xml, application/json;q=0.9, text/html;q=0.8, */*;q=0.5

is then very clear that it desires SVG data primarily, but if the gateway cannot serve that, JSON is second-choice, followed by HTML, and it failing all that, it would accept any other format the gateway can serve. That behavior is less to do with the URL itself, so not sure if that should be part of this standard, or a different standard on gateway behavior? The “Accept HTTP Header” is usually described as part of how the http:// schema is defined, so in that case it would fit that it should be called out in this standard that defines the web3:// schema how it handles request headers, and not just the URL itself?


A method of string encoding that is promoted by the IPFS ecosystem (which many Ethereum projects use, but I haven’t seen any smart contracts use this style of string encoding in their output) is using a “Multibase” identifier.

Multibase as a protocol allows for specifying Base-64-encoding (“m” prefix), as well as JSON-formatted payload (Multicodec 0x0200 prefix), so could be another text format to auto-detect and parse.

2 Likes

Regarding the “resolve modes” for this standard, it currently looks to the resolveMode function to determine what the contract is capable of. Has there been any consideration done to include ERC165 as part of how a gateway determines what the contract is capable of? For widely-used standards like ERC20, ERC721, and ERC1155, if a contract presents an ERC165 interface that advertises it supports one of those standards, that could help make more robust “default” responses?

For example, if a request is made for a contract with no function call in the path, and the gateway tries calling a resolveMode function and it returns “auto”, it could then try calling a supportsInterface function on that contract, and if it returns true for ERC20, then the gateway could return an HTML “card” representation of that contract’s name, symbol, and total supply (the known static metadata options for ERC20 contracts).

This could also affect not just the default return for a contract, but for contracts like ERC721, could make a call like web3://collectionaddress/100 return an HTML representation of token ID 100 from that NFT collection (showing image, properties, current owner, etc.)

Would there be any interest in having “auto” mode be “smarter” by using ERC165 interfaces?

Many thanks for the suggestions! I agree that supporting some widely-adopted standard such as ERC-20, ERC-721 will increase the UX. One concern that from my head is that this creates further dependency of ERC-4804 with other ERCs. Further, this breaks a goal of ERC-4804, which translates an web3:// to a single EVM message (rather than multiple messages and display them in an organized way).

Note that web3:// is highly composable - we can create a web3://, which returns an HTML and further display the information of ERC-20/721. What do you think?

A lot of great thoughts on improving ERC-4804. A couple of my thoughts:

Great! We also found that using suffix of the last argument is not enough to render contract data in “auto” mode. This is a very good summary. One idea that we are discussing is to add a query string to specify the MIME type. E.g., a way may be

.../100?mime=image/svg+xml (Note that / between images and svg should be escaped) or
.../100?mime.types=svg

For data URL, unfortunately, I cannot find an MIME for data URL itself. Do you have any suggestions on that?

I personally won’t complicate the standard with further parsing features in JSON or any other format (e.g., HTML). The reason is that we could use other tools to decode the data in a composable way like

curl web3://contractAddr/method?returns=(string,string,string) | jq '.[1]'

so that we could use the composability of the tools and keep ERC-4804 as simple as possible. What do you think?

This is a great suggestion! We are currently thinking about adding an extension to ERC-4804 to support customized headers (See EIP-6944 and EIP-5219). Definitively we can take this into account to make the standard more powerful!

A proposal to enhance MIME type of Web3 URLs in auto model is here EIP-7087: MIME Type For Web3 URL in Auto Mode

A Chrome-extension to support web3:// is developed by an anonymous community developer here GitHub - ComfyGummy/chrome-web3: Chrome extension for web3:// (ERC-4804) URLs

I have tested it and it runs very well even in very early stage. The work is super fantastic with very deep understanding of Chrome browser and http! It also provides some gif to ease the use of the extension!

Typing a web3 URL

Also, we have a talk about web3:// URL (ERC-4804) at EthCC. Please come if you are interested in it!

“Data URL” doesn’t have a mime-type itself, since it’s a way of specifying mime types for a payload (similarly, “this file has a three-letter extension separated from the filename by a period to specify its type” doesn’t have a mime-type itself).

I would suggest that “Data URL” style payloads be parsed by the gateway as a good way to guess the mime-type. Therefore for queries like .../100 (that don’t specify a mime-type), the gateway has a pretty confident guess at what the mime-type is (same as how double-clicking on a file with a “.PNG” extension, the operating system has a pretty good guess it’s an image file and has a default action to take in that case). With that idea, .../100?mime=image/svg+xml still returns SVG (same as explicitly right-clicking a “.PNG” file and choosing “open with > picture viewer”; it doesn’t hurt anything, it’s just more verbose call than .../100.

Sure, that seems good, to have a few interlocking standards like that.

1 Like

Thanks for the comment. The explicit MIME and dataurl support is proposed here EIP-7087: MIME Type For Web3 URL in Auto Mode. Please take a look :slight_smile:

Hi!

Adding the info here as well on the ERC-4804 “umbrella” :

I have implemented ERC-6944 (adding ERC-5219 as a mode to ERC-4804 web3://) on :

I have published a demo ERC-6944 website at web3://web3-mode-5219.terraformnavigator.eth/ (Terraform NFT explorer) whose source code is at https://etherscan.io/address/0x2b51a751d3c7d3554e28dc72c3b032e5f56aa656#code

1 Like

Hi @qizhou

Question: I have a smartcontract method in which I return a large complex structured data (struct of arrays of struct of strings, ints, …). I want to access that via a web3:// call in auto mode that will return that to me as JSON, but I think I am stuck :
1/ Using returns=(…) does not allow structs && arrays
2/ Generating myself the JSON string in the smartcontract is consuming waay too much gas (and is conceptually wasteful).
Do you see a way to do that, or shall we discuss an extension to the syntax for returns=(…) that handle structs && arrays, as another extension?

I propose this extension spec (while remaining backward compatible) :

  • ?returns=(uint256[]) for an array of uints e.g. [[1, 3]]
  • ?returns=(uint256[],string[]) for a return of 2 args: an array of uints and an array of string e.g. [[1, 3], ["blah", "bloh"]]
  • ?returns=((uint256[],int)) for a return of a single tuple/struct containing an array of uints and an int e.g. [[[1, 3], 5]]
  • ?returns=(string,(uint256[],int)) for a return of 2 args: a string, and a tuple/struct containing an array of uints and an int e.g. ["blah", [[1, 3], 5]]
  • ?returns=((uint256[],(int,address)) for a return of a single tuple/struct containing an array of uints and a tuple/struct of an int and a address e.g. [[[1, 3], [3, "0xabcd"]]]
  • ?returns=((uint256[],string)[]) for a return of an array of tuple/struct containing an array of uints and an int e.g. [[[1, 3], "bb"], [[2, 5], "aa"]]

This above returns everything into JSON arrays. I would like to also propose named vars, so that it returns objects. It would be a varname: prefix to field defs, such as:

  • ?returns=(myattr:(mylist:uint256[],blah:string),bloh:string) which would returns {myattr: {mylist: [2, 4], blah: "boo"}, bloh: "baa"}

If this looks good to you, we could add in on ERC-7087 and broaden its scope?