eeethers.xyz was the first smart contract I wrote that got published off of a testnet. At the time, multiple iterations of this were littered across Rinkby and Ropsten. Ultimately, it went live on Optimism. Feel free to check out the contract on Etherscan.
It was a pretty simple concept. Take the wallet address of whoever was minting the token, and split the it into 6 character chunks so it could be used as a color hex code. Since an address is 42 characters long we can get 7 unique color codes — though you do need to replace the 0x
with a proper value (I used ff
).
string[7] memory colors = [
string.concat('ff', utils.getSlice(3, 6, _a)),
utils.getSlice(7, 12, _a),
utils.getSlice(13, 18, _a),
utils.getSlice(19, 24, _a),
utils.getSlice(25, 30, _a),
utils.getSlice(31, 36, _a),
utils.getSlice(37, 42, _a)
];
The whole project was bootstrapped with hot-chain-svg while dramatically improved the experience of composing an SVG in Solidity.
This:
string.concat(
'<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1000 1000" style="background: #F2F3F5;">',
svg.el(
"filter",
string.concat(svg.prop("id", "filter")),
string.concat(
svg.el("feTurbulence", string.concat(svg.prop("type", "fractalNoise"), svg.prop("baseFrequency", "0.01"), svg.prop("numOctaves", "3"), svg.prop("seed", utils.uint2str(_tokenId)))),
svg.el("feDisplacementMap", string.concat(svg.prop("in", "SourceGraphic"), svg.prop("yChannelSelector", "R"), svg.prop("scale", "99")))
)
),
svg.g(
string.concat(svg.prop("filter", "url(#filter)"), svg.prop("fill", "none"), svg.prop("stroke", string.concat("#ff", colors[0])), svg.prop("stroke-width", "140%"), svg.prop("stroke-dasharray", "99")),
string.concat(
svg.circle(
string.concat(svg.prop("id", "c"), svg.prop("cx", "50%"), svg.prop("cy", "50%"), svg.prop("r", "70%"), svg.prop("style", "transform-origin: center")),
svg.animateTransform(
string.concat(
svg.prop("attributeName", "transform"),
svg.prop("attributeType", "XML"),
svg.prop("type", "rotate"),
svg.prop("from", "0 0 0"),
svg.prop("to", "360 0 0"),
svg.prop("dur", "120s"),
svg.prop("repeatCount", "indefinite")
)
)
),
string.concat(
svg.el("use", string.concat(svg.prop("href", "#c"), svg.prop("stroke", string.concat("#", colors[1])), svg.prop("stroke-dasharray", "99 60"))),
svg.el("use", string.concat(svg.prop("href", "#c"), svg.prop("stroke", string.concat("#", colors[2])), svg.prop("stroke-dasharray", "99 120"))),
svg.el("use", string.concat(svg.prop("href", "#c"), svg.prop("stroke", string.concat("#", colors[3])), svg.prop("stroke-dasharray", "99 180"))),
svg.el("use", string.concat(svg.prop("href", "#c"), svg.prop("stroke", string.concat("#", colors[4])), svg.prop("stroke-dasharray", "99 240"))),
svg.el("use", string.concat(svg.prop("href", "#c"), svg.prop("stroke", string.concat("#", colors[5])), svg.prop("stroke-dasharray", "99 300"))),
svg.el("use", string.concat(svg.prop("href", "#c"), svg.prop("stroke", string.concat("#", colors[6])), svg.prop("stroke-dasharray", "99 360")))
)
)
),
"</svg>"
);
Becomes this:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" height="100%" width="100%">
<script xmlns="" type="text/javascript"/>
<filter id="filter">
<feTurbulence type="fractalNoise" baseFrequency="0.01" numOctaves="3" seed="50"/>
<feDisplacementMap in="SourceGraphic" yChannelSelector="R" scale="99"/>
</filter>
<rect width="100%" height="100%" fill="#F2F3F5"/>
<g filter="url(#filter)" fill="none" stroke="#ffff7bcf" stroke-width="140%" stroke-dasharray="99">
<circle id="c" cx="50%" cy="50%" r="70%" style="transform-origin: center">
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 0 0" to="360 0 0" dur="500s" repeatCount="indefinite"/>
</circle>
<use href="#c" stroke="#484bd0" stroke-dasharray="99 60"/>
<use href="#c" stroke="#7f0dbd" stroke-dasharray="99 120"/>
<use href="#c" stroke="#ae3999" stroke-dasharray="99 180"/>
<use href="#c" stroke="#14baee" stroke-dasharray="99 240"/>
<use href="#c" stroke="#16d405" stroke-dasharray="99 300"/>
<use href="#c" stroke="#a8b272" stroke-dasharray="99 360"/>
</g>
</svg>