If I am a contract that’s composing together multiple SVGs, I’ll probably know the position and z-index of where I want to put my child SVGs. What scenarios do you envision where the child SVG knows what z-index to render at, but the composer does not?
Have you considered using the link tag instead of concatenating SVGs on-chain? Would have to more formally describe the URI format, but as a really rough example:
Ah! That makes total sense. Otherwise the composer would have to parse the SVG to get the total size. Probably a good example to put in the EIP’s Rationale section!
Oh, I didn’t mean to imply that there wouldn’t be a z-index in the composer. Just that you’d probably have setBackground(address, uint256) and addAttachment(address, uint256) in the composer, and those would know what z-index to use, instead of the child only being usable at a single z-index.
I think this step could be implemented by preprocessing the SVG, and while it would increase the amount of work done off-chain, I think it might be worth while to reduce the amount of work on-chain. For example, this would be super useful to any NFT that currently base64 encodes data on the fly.
That said, I’d be happy with concatenation as well. Just wanted to throw the suggestion out there.
Concatenated SVG on-chain will work when the image size is small, and when the pfp image size is big (the image may have more details), the cost of uploading metadata will be very high (cyberbroker used nearly 100 ETH to upload their metadata). Also, the read gas could be very high and may exceed the gas limit.
SVG format has great composability, and it can combine multiple PNG images into an SVG image by smart contracts in a very efficient way. It will release all artists’ creativity by enabling PNG image composability.
But the PNG files will consume a lot of storage, so we can either upload them to Ethereum by consuming a lot of gas or use a programmable storage L2 to store the PNG and assemble them according to the state of L1’s NFT.
We have a super cool demo here and use Web3Q as the programmable storage L2 layer.
Really cool EIP. Thanks for writing it and building such cool projects!
Just reading it and got a few comments
A) The EIP should focus on the technical specification only
If the caller of the render function composes an SVG NFT they must have rights to use the SVG body in a composable SVG. The token holder could optionally hold both the SVG and rendered SVG NFTs or the token holder could hold the SVG NFT, and the SVG NFT could hold the rendered SVG NFT.
This should not be specified in my opinion and I strongly feel about this, the EIP should focus on the technical spec.
B) viewbox information
I see that the rendered svg omits the SVG tag so it can be composed more easily, unfortunately it removes an important aspect of many SVG: the viewbox on which they were designed for.
As such we should somehow add that back in the returned data.
I had a technical question about the SVG spec version considered. Should the renderTokenById function only support SVG 1.1 or SVG 2 (currently still in Candidate Recommendation) is OK ?
Concerning the viewBox, I made a few tests with a composable SVG marker. And after grabbing some random SVGs on the internet, it appears that wrapping the content in an <svg viewBox="0 0 X X"> (if not already present) was mandatory to control the final rendering.
This can be done either by the composed SVG NFT or by the composable SVG NFT.
Which raise 2 questions for me:
What do I want to return in the renderTokenById and control the rendering (to allow full composition with svg elements and taking the risk of being cropped or restrict it) ? And also should it be the same as tokenURI ?
Who should handle it ?
Both are outside of this EIP for me and I like the simple yet very efficient renderTokenById(uint256 id).
I think a recommandation guide would help heading in the same direction.
Also maybe later, an additional function returning an ENUM or an identifier, could specify the rendering, allowed composition uses and maybe pricing (a new kind of royalties/fees for using this composable NFT) ?
We have been returning an SVG group element, with accessories, background and pfp all using the same coordinates (viewBox) for Party Panda 2.0/Merge Bears. Essentially not including the <svg> element.
So tokenURI includes the svg element whilst renderTokenById is just grouped elements.
It was suggested by one of the editors that we standardize viewBox="0 0 500 500". An early draft of the EIP had sizing but we removed to keep the EIP as simple as possible.
I think the composer should handle any scaling/transforms, as it is their responsibility to compose the SVGs as they require.
I played with translate and scale on a Merge Bear. I used the renderTokenById function from a Loogie Bow and an OE40 and manually added to a Merge Bear in https://www.svgviewer.dev/ and adjusted the translate and scale so that it fit.
Example manual SVG with Merge Bear, Crown, Bow and OE40:
Looking at this example, ERC4883 composers could optionally accept translate and scale so that the end user could craft the SVG as desired.
Agree. We are still very early, as we work out how to compose, especially across different ERC4883 projects.
I removed the rights requirement from the EIP as suggested by @wighawag
My concern was raised by the <use> element <use> - SVG: Scalable Vector Graphics | MDN and its older xlink:href with the associated namespace xlink: that might not be supported at some point by browsers. But is still heavily used…
I am not sure it would be worth adding the SVG version to the EIP. as there is some backwards compatibility. If a composer attempts to compose with an incompatible SVG then the user can undo any composing/linking.