BasePaint is a lovely new project on the Base network - each day, owners of Brush NFTs come together to create a collaborative pixel art piece. The piece gets minted as an open edition, and proceeds are split between the artists.
Let's walk through the contract!
The contract begins by declaring the address for the brushes contract, along with the duration of an epoch. It also defines a Canvas type, along with a mapping of Canvases and a timestamp startedAt for when the experiment starts.
We then initialize the openEditionPrice variable along with the owner fee % and a uint for how much the owner has earned.
Next, we declare a bunch of events for the project start, paints, artist and owner earnings and withdrawals, OE fee % and price updates.
In the constructor, we initialize the brushes contract and epoch duration upon deployment.
The mint function (for the daily OEs) takes in a day and amount. It checks that the project has started, the day is correct, that the canvas has been painted, and that enough ETH was sent.
It then mints the token and splits the earnings between the owner and the artist pool.
The paint() function is called by each artist with the day, tokenId of their brush, and the pixels they're painting.
After checking the input data is valid, it updates the amount of the brush used along with other relevant Canvas data like the artist contribution amounts.
paint() emits an event with the pixel data for each Canvas - the BasePaint backend can read which pixels have been painted by whom, and assemble the artwork accordingly. Even though the artwork itself is not on-chain, anyone can index the events to see a canvas's pixel data.
Next, contribution() returns the amount of paint contributed by an artist on a given canvas day. brushUsed() returns the total amount on a canvas entirely. And today() represents the amount of days since the startedAt timestamp.
authorWithdraw() allows artists to claim their share of earnings from BasePaint edition sales. They pass in the days they've painted, and for each day it calculates their earnings based on their relative paint contribution for that piece. Then it sends them all of that ETH.
start() is called by the owner to begin the BasePaint project, and sets startedAt to the current timestamp.
setURI() allows the owner to set a new baseURI for the token metadata, and setOwnerFee allows them to update the fee % from BasePaint sales - as long as it is under 100%.
setOpenEditionPrice lets the owner update the price of an OE to something new.
Lastly, withdraw() allows the owner to withdraw all of the funds accrued to the owner (ownerEarned) to a given wallet.
And that is the @basepaint_xyz contract! You can view the full contract code here.
There's also a separate contract for Brush NFTs, which tracks the amount of paint allotted to a given brush along with the ability to upgrade or increase the power of a brush - but we won't dive into that on this thread.
If you enjoyed this essay, share it and give me a follow on Twitter. I write daily about onchain software and media.