Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/HTMLRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
pragma solidity ^0.8.13;

import {SSTORE2} from "solady/utils/SSTORE2.sol";

import {LibBytes} from "solady/utils/LibBytes.sol";
import {LibZip} from "solady/utils/LibZip.sol";
interface IOwnable {
function owner() external view returns (address);
}
Expand Down Expand Up @@ -44,7 +45,11 @@ contract HTMLRegistry {
function _html(address author, address target, uint256 version) internal view returns (bytes memory) {
address ptr = sPtrs[author][target][version];
if (ptr == address(0)) return new bytes(0);
return SSTORE2.read(ptr);
bytes memory data = SSTORE2.read(ptr);

if (bytes4(bytes32(data)) == bytes4(0xffffffff)) return LibZip.flzDecompress(LibBytes.slice(data, 4));

return data;
}

function setHtml(address target, bytes calldata htmlData) external onlyAuthorized(target) {
Expand Down
50 changes: 50 additions & 0 deletions test/HTMLRegistry.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
pragma solidity ^0.8.13;

import {Test} from "forge-std/Test.sol";
import {console2} from "forge-std/console2.sol";
import {HTMLRegistry} from "../src/HTMLRegistry.sol";
import {LibZip} from "solady/utils/LibZip.sol";

contract HTMLRegistryTest is Test {
HTMLRegistry public registry;
Expand Down Expand Up @@ -101,6 +103,54 @@ contract HTMLRegistryTest is Test {
assertEq(registry.html(alice, alice, 2), new bytes(0));
}

function test_html_decompressesWhenPrefixed() public {
bytes memory compressed = bytes.concat(bytes4(0xffffffff), LibZip.flzCompress(_HTML));
vm.prank(alice);
registry.setHtml(alice, compressed);

assertEq(registry.html(alice, alice), _HTML);
}

function test_html_returnsRawWhenPrefixDoesNotMatch() public {
bytes memory payload = bytes.concat(bytes4(0xdeadbeef), bytes("raw bytes"));
vm.prank(alice);
registry.setHtml(alice, payload);

assertEq(registry.html(alice, alice), payload);
}

function test_html_returnsRawWhenDataTooShortForPrefix() public {
bytes memory payload = hex"010203";
vm.prank(alice);
registry.setHtml(alice, payload);

assertEq(registry.html(alice, alice), payload);
}

function test_storageMetrics_plainVsCompressed() public {
bytes memory compressedBody = LibZip.flzCompress(_HTML);
bytes memory compressedPayload = bytes.concat(bytes4(0xffffffff), compressedBody);

vm.startPrank(alice);
uint256 gasStartPlain = gasleft();
registry.setHtml(alice, _HTML);
uint256 gasUsedPlain = gasStartPlain - gasleft();

uint256 gasStartCompressed = gasleft();
registry.setHtml(alice, compressedPayload);
uint256 gasUsedCompressed = gasStartCompressed - gasleft();
vm.stopPrank();

assertEq(registry.html(alice, alice, 1), _HTML);
assertEq(registry.html(alice, alice, 2), _HTML);

console2.log("plain length", _HTML.length);
console2.log("compressed length", compressedBody.length);
console2.log("compressed+selector length", compressedPayload.length);
console2.log("plain write gas", gasUsedPlain);
console2.log("compressed write gas", gasUsedCompressed);
}

function test_emitsHtmlSet() public {
vm.startPrank(alice);
vm.expectEmit(true, true, false, true);
Expand Down
Loading