Optimize contracts#123
Conversation
There was a problem hiding this comment.
Pull Request Overview
This pull request optimizes the contract structure by flattening the nested ContentInfo struct into the main Ethscription struct and reduces field sizes from uint256 to uint48 where appropriate. This improves gas efficiency by reducing storage slots and eliminating redundant nested structure access.
- Flattened
ContentInfofields directly into theEthscriptionstruct - Changed numeric field types from uint256/uint64 to uint48 for gas optimization
- Removed
mediaTypeandmimeSubtypefields from storage, now derived frommimetypeat runtime
Reviewed Changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/storage_reader.rb | Updates ABI decoding to match flattened struct and derives media_type/mime_subtype from mimetype |
| lib/block_validator.rb | Removes validation for media_type and mime_subtype fields that are no longer stored |
| contracts/src/Ethscriptions.sol | Flattens ContentInfo into Ethscription struct and optimizes field sizes |
| contracts/src/EthscriptionsProver.sol | Updates struct fields to use uint48 types and adjusts field access patterns |
| contracts/src/libraries/EthscriptionsRendererLib.sol | Updates field access to use flattened struct fields |
| app/models/ethscription_transaction.rb | Removes media_type and mime_subtype from calldata construction |
| contracts/test/*.sol | Updates test files to remove mediaType and mimeSubtype parameters |
| contracts/script/*.sol | Updates script files to match new struct format |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| uint48 createdAt; | ||
| uint48 l1BlockNumber; |
There was a problem hiding this comment.
Using uint48 for timestamps and block numbers may cause overflow issues. Block numbers and timestamps can exceed the uint48 maximum value (281,474,976,710,655). Consider using uint64 or keeping uint256 for these critical fields to prevent future overflow.
| uint48 l2BlockNumber; | ||
| uint48 l2BlockTimestamp; | ||
| uint48 l1BlockNumber; |
There was a problem hiding this comment.
Using uint48 for block numbers and timestamps risks overflow. Ethereum block numbers and timestamps will eventually exceed uint48's maximum value of ~281 trillion. This could cause silent overflow and incorrect data storage.
|
|
||
| # Derive media_type and mime_subtype from mimetype | ||
| mimetype = ethscription_data[6] # mimetype is at index 6 | ||
| media_type, mime_subtype = mimetype.split('/', 2) if mimetype |
There was a problem hiding this comment.
The split method uses 2 as the limit parameter, but this should be at most 2 parts for a mimetype (e.g., 'text/plain'). Using split('/', 2) correctly limits to 2 parts, but consider using just split('/') or adding validation that exactly 2 parts exist.
| media_type, mime_subtype = mimetype.split('/', 2) if mimetype | |
| if mimetype | |
| parts = mimetype.split('/') | |
| if parts.size == 2 | |
| media_type, mime_subtype = parts | |
| else | |
| media_type = nil | |
| mime_subtype = nil | |
| end | |
| end |
| mimetype = data_uri.mimetype.to_s | ||
| media_type = mimetype&.split('/')&.first | ||
| mime_subtype = mimetype&.split('/')&.last | ||
| mimetype = data_uri.mimetype.to_s.first(MAX_MIMETYPE_LENGTH) |
There was a problem hiding this comment.
The first method on String returns the first character, not the first N characters. Use [0, MAX_MIMETYPE_LENGTH] or truncate(MAX_MIMETYPE_LENGTH, omission: '') instead to limit the mimetype length properly.
| mimetype = data_uri.mimetype.to_s.first(MAX_MIMETYPE_LENGTH) | |
| mimetype = data_uri.mimetype.to_s[0, MAX_MIMETYPE_LENGTH] |
|
bugbot run |
Note
Flattens on-chain Ethscription storage (removes nested ContentInfo and mediaType/mimeSubtype), updates ABI/calldata, renderer, prover, genesis script, Ruby readers/validator, and tests; also enforces a max mimetype length.
Ethscription(promotecontentUriHash,contentSha,mimetype,esip6; addl1BlockHash; packuint48fields); removeContentInfoand allmediaType/mimeSubtypeusage; update getters, content lookups, event emission, and storage writes.etsc.mimetypeand flattened hashes; drop media/subtype attributes; adjust attribute JSON and media URI logic.uint48fields; includel1BlockHash; read flattened fields.createGenesisEthscription; remove media/subtype params; parse JSON without them.mediaType/mimeSubtypefromCreateEthscriptionParamsusage and assertions; update expected attributes (fewer traits) and field accessors.createEthscription(no media/subtype); addMAX_MIMETYPE_LENGTHand truncate mimetype.uint48fields and indexes; updateget_ethscription_with_content/get_ethscriptionto return flattened fields; remove media/subtype outputs.media_type/mime_subtype; note they’re derived; continue mimetype/esip6 checks.(bytes32,bytes32,address,bytes,string,bool,(string,string,bytes))for create; fix event emission to use flattenedcontentUriHash/contentSha.Written by Cursor Bugbot for commit 33c8891. This will update automatically on new commits. Configure here.