EIP-4883: Composable SVG NFT

EIP-4883 Composable SVG NFT

Discussion for EIP-4883

NFT has public render function returning SVG body that can be composed.

SVG specification Rendering model: SVG 1.1 specification section 3


Implementations of composable SVGs:

BuidlGuidl BTF - Composable SVG NFTs demo

Fancy Loogies & Loogie Tanks

Party Panda

Example of a Party Panda NFT with a background and foreground:
Party Panda #88 on Rinkeby OpenSea

Render function name

Need to standardize render function name:

Loogies uses renderTokenById

Party Panda uses render



I added that the caller of render must have rights to use the SVG body in a composed SVG.


I haven’t specified how this must be done, so any relationship can be used.

When @AlexPartyPanda and I first started playing with adding accessories to pfps we had a token holder owning both the pfp and the accessory and creating a link between the two.

FancyLoogies introduced us to that the pfp could be the token holder of the accessory and that a linkage could be setup on transfer.

Need to find wording to describe the two tokens, composer and composee feel a bit clumsy.


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:

  <image width="10" height="10" href="eth://0x1234...abcd/image?u256=34"></image>
1 Like

Two more non-formatting related questions:

Should the optional methods revert if they aren’t supported? Would they be better placed in a separate optional interface?

What units are width and height in?

1 Like

Great questions @SamWilsn :pray:

Need to agree if zindex, width and height are required in the EIP or if a render function is sufficient.

A test was adding Party Pandas and Nouns glasses to a Loogie Tank using only a render function. Need to dig in if sizing would help here, as currently the elements go out of the tank.

Party Pandas in a Loogie Tank

In PartyPanda there is permissionless linking, a token holder can add a child SVG NFT that is either a background or an accessory by transferring ownership of the child to the composable NFT.

Though this could be implemented in the child SVG NFT to provide a zindex as part of the transfer, so then it wouldn’t need to be part of the standard.

I hadn’t considered using a link tag.

Concatenating SVGs on-chain works today, it allows for the child SVG to change based on state, and when combined with the parent holding the child, enforces ownership.

I assume a new URI format would require a huge effort to get adoption, compared with the output of concatenated SVGs working with current browsers. (See the SVG from OpenSea with composable SVGs)

The optional methods should be in optional interfaces.

Still need to agree if zindex and size are required in the EIP.

“For SVG-specific properties, the length unit identifier is optional. If a unit is not provided, the length value represents a distance in the current user coordinate system.”

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.

1 Like

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.

As @SamWilsn said, “link” tag could help by reducing the on-chain image size, but as @abcoathup said, opensea compatibility is an issue right now. The SVG image with the image link could not be rendered properly by opensea, it shows an empty image when I tested it on rinkeby (https://testnets.opensea.io/assets/0x618d06a965917794c9df3e5f875ce3a63c6fe250/1)

it seems that there is no perfect tech solution for composable NFT


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.

The format will be like this:

 <svg viewBox="0 0 1000 1000">
     <image xlink:href="data:image/png;base64,', Base64.encode(bgPng), '"/>
     <image xlink:href="data:image/png;base64,', Base64.encode(accessoriesPng), '"/>

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.

1 Like