Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NounsDescriptorV3 #864

Merged
merged 14 commits into from
Nov 11, 2024
1 change: 1 addition & 0 deletions packages/nouns-contracts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ WALLET_PUBLIC_KEY=
WALLET_PRIVATE_KEY=

FOUNDRY_PROFILE=lite
RPC_MAINNET=
181 changes: 181 additions & 0 deletions packages/nouns-contracts/contracts/NounsArt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,154 @@ contract NounsArt is INounsArt {
emit GlassesAdded(imageCount);
}

/**
* @notice Replace all pages of body images with new ones.
* @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array,
* and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateBodies(
bytes calldata encodedCompressed,
uint80 decompressedLength,
uint16 imageCount
) external onlyDescriptor {
replaceTraitData(bodiesTrait, encodedCompressed, decompressedLength, imageCount);

emit BodiesUpdated(imageCount);
}

/**
* @notice Replace all pages of accessory images with new ones.
* @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array,
* and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateAccessories(
bytes calldata encodedCompressed,
uint80 decompressedLength,
uint16 imageCount
) external onlyDescriptor {
replaceTraitData(accessoriesTrait, encodedCompressed, decompressedLength, imageCount);

emit AccessoriesUpdated(imageCount);
}

/**
* @notice Replace all pages of head images with new ones.
* @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array,
* and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateHeads(
bytes calldata encodedCompressed,
uint80 decompressedLength,
uint16 imageCount
) external override onlyDescriptor {
replaceTraitData(headsTrait, encodedCompressed, decompressedLength, imageCount);

emit HeadsUpdated(imageCount);
}

/**
* @notice Replace all pages of glasses images with new ones.
* @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array,
* and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateGlasses(
bytes calldata encodedCompressed,
uint80 decompressedLength,
uint16 imageCount
) external onlyDescriptor {
replaceTraitData(glassesTrait, encodedCompressed, decompressedLength, imageCount);

emit GlassesUpdated(imageCount);
}

/**
* @notice Replace all pages of body images with new ones from an existing storage contract.
* @param pointer the address of a contract where the image batch was stored using SSTORE2. The data
* format is expected to be like {encodedCompressed}: bytes created by taking a string array of
* RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateBodiesFromPointer(
address pointer,
uint80 decompressedLength,
uint16 imageCount
) external onlyDescriptor {
replaceTraitData(bodiesTrait, pointer, decompressedLength, imageCount);

emit BodiesUpdated(imageCount);
}

/**
* @notice Replace all pages of accessory images with new ones from an existing storage contract.
* @param pointer the address of a contract where the image batch was stored using SSTORE2. The data
* format is expected to be like {encodedCompressed}: bytes created by taking a string array of
* RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateAccessoriesFromPointer(
address pointer,
uint80 decompressedLength,
uint16 imageCount
) external onlyDescriptor {
replaceTraitData(accessoriesTrait, pointer, decompressedLength, imageCount);

emit AccessoriesUpdated(imageCount);
}

/**
* @notice Replace all pages of head images with new ones from an existing storage contract.
* @param pointer the address of a contract where the image batch was stored using SSTORE2. The data
* format is expected to be like {encodedCompressed}: bytes created by taking a string array of
* RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateHeadsFromPointer(
address pointer,
uint80 decompressedLength,
uint16 imageCount
) external override onlyDescriptor {
replaceTraitData(headsTrait, pointer, decompressedLength, imageCount);

emit HeadsUpdated(imageCount);
}

/**
* @notice Replace all pages of glasses images with new ones from an existing storage contract.
* @param pointer the address of a contract where the image batch was stored using SSTORE2. The data
* format is expected to be like {encodedCompressed}: bytes created by taking a string array of
* RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate.
* @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate.
* @param imageCount the number of images in this batch; used when searching for images among batches.
* @dev This function can only be called by the descriptor.
*/
function updateGlassesFromPointer(
address pointer,
uint80 decompressedLength,
uint16 imageCount
) external onlyDescriptor {
replaceTraitData(glassesTrait, pointer, decompressedLength, imageCount);

emit GlassesUpdated(imageCount);
}

/**
* @notice Get the number of available Noun `backgrounds`.
*/
Expand Down Expand Up @@ -405,6 +553,39 @@ contract NounsArt is INounsArt {
backgrounds.push(_background);
}

function replaceTraitData(
Trait storage trait,
bytes calldata encodedCompressed,
uint80 decompressedLength,
uint16 imageCount
) internal {
if (encodedCompressed.length == 0) {
revert EmptyBytes();
}
delete trait.storagePages;
delete trait.storedImagesCount;

addPage(trait, encodedCompressed, decompressedLength, imageCount);
}

function replaceTraitData(
Trait storage trait,
address pointer,
uint80 decompressedLength,
uint16 imageCount
) internal {
if (decompressedLength == 0) {
revert BadDecompressedLength();
}
if (imageCount == 0) {
revert BadImageCount();
}
delete trait.storagePages;
delete trait.storedImagesCount;

addPage(trait, pointer, decompressedLength, imageCount);
}

function addPage(
Trait storage trait,
bytes calldata encodedCompressed,
Expand Down
Loading
Loading