diff --git a/app/models/ethscription_transaction.rb b/app/models/ethscription_transaction.rb
index 4c70d9e..4c85109 100644
--- a/app/models/ethscription_transaction.rb
+++ b/app/models/ethscription_transaction.rb
@@ -199,7 +199,7 @@ def build_create_calldata
# Encode parameters
params = [
- tx_hash_bin, # bytes32 transactionHash
+ tx_hash_bin, # bytes32 ethscriptionId (L1 tx hash)
content_uri_hash, # bytes32 contentUriHash
owner_bin, # address
raw_content, # bytes content
diff --git a/contracts/script/L2Genesis.s.sol b/contracts/script/L2Genesis.s.sol
index 57d09d6..b477898 100644
--- a/contracts/script/L2Genesis.s.sol
+++ b/contracts/script/L2Genesis.s.sol
@@ -13,11 +13,11 @@ import "forge-std/console.sol";
/// @dev Used only during genesis, then replaced with the real Ethscriptions contract
contract GenesisEthscriptions is Ethscriptions {
- /// @notice Store a genesis ethscription transaction hash for later event emission
+ /// @notice Store a genesis ethscription ID for later event emission
/// @dev Internal function only used during genesis setup
- /// @param transactionHash The transaction hash to store
- function _storePendingGenesisEvent(bytes32 transactionHash) internal {
- pendingGenesisEvents.push(transactionHash);
+ /// @param ethscriptionId The ethscription ID (L1 tx hash) to store
+ function _storePendingGenesisEvent(bytes32 ethscriptionId) internal {
+ pendingGenesisEvents.push(ethscriptionId);
}
/// @notice Create an ethscription with all values explicitly set for genesis
@@ -29,7 +29,7 @@ contract GenesisEthscriptions is Ethscriptions {
bytes32 l1BlockHash
) public returns (uint256 tokenId) {
require(creator != address(0), "Invalid creator");
- require(ethscriptions[params.transactionHash].creator == address(0), "Ethscription already exists");
+ require(ethscriptions[params.ethscriptionId].creator == address(0), "Ethscription already exists");
// Check protocol uniqueness using content URI hash
if (firstEthscriptionByContentUri[params.contentUriHash] != bytes32(0)) {
@@ -40,10 +40,10 @@ contract GenesisEthscriptions is Ethscriptions {
bytes32 contentSha = _storeContent(params.content);
// Mark content URI as used by storing this ethscription's tx hash
- firstEthscriptionByContentUri[params.contentUriHash] = params.transactionHash;
+ firstEthscriptionByContentUri[params.contentUriHash] = params.ethscriptionId;
// Set all values including genesis-specific ones
- ethscriptions[params.transactionHash] = Ethscription({
+ ethscriptions[params.ethscriptionId] = Ethscription({
// Fixed-size fields
contentUriHash: params.contentUriHash,
contentSha: contentSha,
@@ -66,8 +66,8 @@ contract GenesisEthscriptions is Ethscriptions {
// Use ethscription number as token ID
tokenId = totalSupply();
- // Store the mapping from token ID to transaction hash
- tokenIdToTransactionHash[tokenId] = params.transactionHash;
+ // Store the mapping from token ID to ethscription ID
+ tokenIdToEthscriptionId[tokenId] = params.ethscriptionId;
// Token count is automatically tracked by enumerable's _update
@@ -82,7 +82,7 @@ contract GenesisEthscriptions is Ethscriptions {
// Store the transaction hash so all events can be emitted later
// The emission logic in _emitPendingGenesisEvents will figure out
// what events to emit based on the ethscription data
- _storePendingGenesisEvent(params.transactionHash);
+ _storePendingGenesisEvent(params.ethscriptionId);
// Skip token handling for genesis
}
@@ -333,7 +333,7 @@ contract L2Genesis is Script {
// Create params struct with parsed data from JSON
// The JSON already has all the properly processed data
Ethscriptions.CreateEthscriptionParams memory params;
- params.transactionHash = vm.parseJsonBytes32(json, string.concat(basePath, ".transaction_hash"));
+ params.ethscriptionId = vm.parseJsonBytes32(json, string.concat(basePath, ".transaction_hash"));
params.contentUriHash = vm.parseJsonBytes32(json, string.concat(basePath, ".content_uri_hash"));
params.initialOwner = initialOwner;
params.content = vm.parseJsonBytes(json, string.concat(basePath, ".content"));
diff --git a/contracts/script/TestTokenUri.s.sol b/contracts/script/TestTokenUri.s.sol
index 76e7406..5fc7ab9 100644
--- a/contracts/script/TestTokenUri.s.sol
+++ b/contracts/script/TestTokenUri.s.sol
@@ -17,7 +17,7 @@ contract TestTokenUri is Script {
// Test case 1: Plain text (should use viewer)
vm.prank(address(0x1111));
eth.createEthscription(Ethscriptions.CreateEthscriptionParams({
- transactionHash: keccak256("text1"),
+ ethscriptionId: keccak256("text1"),
contentUriHash: keccak256("data:text/plain,Hello World!"),
initialOwner: address(0x1111),
content: bytes("Hello World!"),
@@ -29,7 +29,7 @@ contract TestTokenUri is Script {
// Test case 2: JSON content (should use viewer with pretty print)
vm.prank(address(0x2222));
eth.createEthscription(Ethscriptions.CreateEthscriptionParams({
- transactionHash: keccak256("json1"),
+ ethscriptionId: keccak256("json1"),
contentUriHash: keccak256('data:application/json,{"p":"erc-20","op":"mint","tick":"test","amt":"1000"}'),
initialOwner: address(0x2222),
content: bytes('{"p":"erc-20","op":"mint","tick":"test","amt":"1000"}'),
@@ -41,7 +41,7 @@ contract TestTokenUri is Script {
// Test case 3: HTML content (should pass through directly)
vm.prank(address(0x3333));
eth.createEthscription(Ethscriptions.CreateEthscriptionParams({
- transactionHash: keccak256("html1"),
+ ethscriptionId: keccak256("html1"),
contentUriHash: keccak256('data:text/html,
Ethscriptions Rule!
'),
initialOwner: address(0x3333),
content: bytes('Ethscriptions Rule!
'),
@@ -54,7 +54,7 @@ contract TestTokenUri is Script {
bytes memory redPixelPng = Base64.decode("iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAm0lEQVR42mNgGITgPxTTxvBleTo0swBsOK0s+N8aJkczC1AMR7KAKpb8v72xAY5hFsD4lFoCN+j56ZUoliBbSoklGIZjwxRbQAjT1YK7d+82kGUBeuQii5FrAYYrL81NwCpGFQtoEUT/6RoHWAyknQV0S6ZI5RE6Jt8CZIOOHTuGgR9Fq5FkCf19QM3wx5rZKHEtsRZQt5qkhgUAR6cGaUehOD4AAAAASUVORK5CYII=");
vm.prank(address(0x4444));
eth.createEthscription(Ethscriptions.CreateEthscriptionParams({
- transactionHash: keccak256("image1"),
+ ethscriptionId: keccak256("image1"),
contentUriHash: keccak256("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAm0lEQVR42mNgGITgPxTTxvBleTo0swBsOK0s+N8aJkczC1AMR7KAKpb8v72xAY5hFsD4lFoCN+j56ZUoliBbSoklGIZjwxRbQAjT1YK7d+82kGUBeuQii5FrAYYrL81NwCpGFQtoEUT/6RoHWAyknQV0S6ZI5RE6Jt8CZIOOHTuGgR9Fq5FkCf19QM3wx5rZKHEtsRZQt5qkhgUAR6cGaUehOD4AAAAASUVORK5CYII="),
initialOwner: address(0x4444),
content: redPixelPng,
@@ -66,7 +66,7 @@ contract TestTokenUri is Script {
// Test case 5: CSS content (should use viewer)
vm.prank(address(0x5555));
eth.createEthscription(Ethscriptions.CreateEthscriptionParams({
- transactionHash: keccak256("css1"),
+ ethscriptionId: keccak256("css1"),
contentUriHash: keccak256("data:text/css,body { background: #000; color: #0f0; font-family: 'Courier New'; }"),
initialOwner: address(0x5555),
content: bytes("body { background: #000; color: #0f0; font-family: 'Courier New'; }"),
@@ -110,4 +110,4 @@ contract TestTokenUri is Script {
console.log("=== PASTE ANY OF THE ABOVE data: URIs INTO YOUR BROWSER ===");
}
-}
\ No newline at end of file
+}
diff --git a/contracts/src/CollectionsManager.sol b/contracts/src/CollectionsManager.sol
index 06b392e..975d7de 100644
--- a/contracts/src/CollectionsManager.sol
+++ b/contracts/src/CollectionsManager.sol
@@ -36,7 +36,7 @@ contract CollectionsManager is IProtocolHandler {
// Runtime state for a collection (separate from metadata)
struct CollectionState {
address collectionContract;
- bytes32 createTxHash;
+ bytes32 createEthscriptionId;
uint256 currentSize;
bool locked;
}
@@ -135,7 +135,7 @@ contract CollectionsManager is IProtocolHandler {
event CollectionLocked(bytes32 indexed collectionId);
// Mirror success signaling so indexers can detect success without relying on router
- event ProtocolHandlerSuccess(bytes32 indexed transactionHash, string protocol);
+ event ProtocolHandlerSuccess(bytes32 indexed ethscriptionId, string protocol);
modifier onlyEthscriptions() {
require(msg.sender == ethscriptions, "Only Ethscriptions contract");
@@ -169,7 +169,7 @@ contract CollectionsManager is IProtocolHandler {
// Store collection state
collectionState[collectionId] = CollectionState({
collectionContract: collectionContract,
- createTxHash: txHash,
+ createEthscriptionId: txHash,
currentSize: 0,
locked: false
});
@@ -408,7 +408,7 @@ contract CollectionsManager is IProtocolHandler {
/// @notice Handle transfer notification from Ethscriptions contract
/// @dev When an ethscription that's part of a collection is transferred, sync the ERC721
function onTransfer(
- bytes32 txHash,
+ bytes32 ethscriptionId,
address from,
address to
) external override onlyEthscriptions {
diff --git a/contracts/src/Ethscriptions.sol b/contracts/src/Ethscriptions.sol
index f23602a..877fd3a 100644
--- a/contracts/src/Ethscriptions.sol
+++ b/contracts/src/Ethscriptions.sol
@@ -50,7 +50,7 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
}
struct CreateEthscriptionParams {
- bytes32 transactionHash;
+ bytes32 ethscriptionId;
bytes32 contentUriHash; // SHA256 of raw content URI (for protocol uniqueness)
address initialOwner;
bytes content; // Raw decoded bytes (not Base64)
@@ -73,7 +73,7 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
// STATE VARIABLES
// =============================================================
- /// @dev Transaction hash => Ethscription data
+ /// @dev Ethscription ID (L1 tx hash) => Ethscription data
mapping(bytes32 => Ethscription) internal ethscriptions;
/// @dev Content SHA => SSTORE2 pointers array
@@ -83,8 +83,8 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
/// @dev bytes32(0) means unused, non-zero means the content URI has been used
mapping(bytes32 => bytes32) public firstEthscriptionByContentUri;
- /// @dev Mapping from ethscription number (token ID) to transaction hash
- mapping(uint256 => bytes32) public tokenIdToTransactionHash;
+ /// @dev Mapping from token ID (ethscription number) to ethscription ID (L1 tx hash)
+ mapping(uint256 => bytes32) public tokenIdToEthscriptionId;
/// @dev Protocol registry - maps protocol names to handler addresses
mapping(string => address) public protocolHandlers;
@@ -117,7 +117,7 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
/// @notice Emitted when a new ethscription is created
event EthscriptionCreated(
- bytes32 indexed transactionHash,
+ bytes32 indexed ethscriptionId,
address indexed creator,
address indexed initialOwner,
bytes32 contentUriHash,
@@ -129,7 +129,7 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
/// @dev This event matches the Ethscriptions protocol transfer semantics where 'from' is the initiator
/// For creations, this shows transfer from creator to initial owner (not from address(0))
event EthscriptionTransferred(
- bytes32 indexed transactionHash,
+ bytes32 indexed ethscriptionId,
address indexed from,
address indexed to,
uint256 ethscriptionNumber
@@ -140,14 +140,14 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
/// @notice Emitted when a protocol handler operation fails but ethscription continues
event ProtocolHandlerFailed(
- bytes32 indexed transactionHash,
+ bytes32 indexed ethscriptionId,
string protocol,
bytes revertData
);
/// @notice Emitted when a protocol handler operation succeeds
event ProtocolHandlerSuccess(
- bytes32 indexed transactionHash,
+ bytes32 indexed ethscriptionId,
string protocol,
bytes returnData
);
@@ -162,11 +162,17 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
_;
}
- /// @notice Modifier to require that an ethscription exists
- /// @param transactionHash The transaction hash to check
- modifier requireExists(bytes32 transactionHash) {
- if (!_ethscriptionExists(transactionHash)) revert EthscriptionDoesNotExist();
- _;
+ /// @notice Resolve and validate an ethscription (by ID) or revert
+ function _getEthscriptionOrRevert(bytes32 ethscriptionId) internal view returns (Ethscription storage ethscription) {
+ if (!_ethscriptionExists(ethscriptionId)) revert EthscriptionDoesNotExist();
+ ethscription = ethscriptions[ethscriptionId];
+ }
+
+ /// @notice Resolve and validate an ethscription (by tokenId) or revert
+ function _getEthscriptionOrRevert(uint256 tokenId) internal view returns (Ethscription storage ethscription) {
+ bytes32 id = tokenIdToEthscriptionId[tokenId];
+ if (!_ethscriptionExists(id)) revert TokenDoesNotExist();
+ ethscription = ethscriptions[id];
}
// =============================================================
@@ -199,20 +205,20 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
address creator = msg.sender;
if (creator == address(0)) revert InvalidCreator();
- if (_ethscriptionExists(params.transactionHash)) revert EthscriptionAlreadyExists();
+ if (_ethscriptionExists(params.ethscriptionId)) revert EthscriptionAlreadyExists();
bool contentUriAlreadySeen = firstEthscriptionByContentUri[params.contentUriHash] != bytes32(0);
if (contentUriAlreadySeen) {
if (!params.esip6) revert DuplicateContentUri();
} else {
- firstEthscriptionByContentUri[params.contentUriHash] = params.transactionHash;
+ firstEthscriptionByContentUri[params.contentUriHash] = params.ethscriptionId;
}
// Store content and get content SHA (of raw bytes)
bytes32 contentSha = _storeContent(params.content);
- ethscriptions[params.transactionHash] = Ethscription({
+ ethscriptions[params.ethscriptionId] = Ethscription({
contentUriHash: params.contentUriHash,
contentSha: contentSha,
l1BlockHash: l1Block.hash(),
@@ -230,8 +236,8 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
// Use ethscription number as token ID
tokenId = totalSupply();
- // Store the mapping from token ID to transaction hash
- tokenIdToTransactionHash[tokenId] = params.transactionHash;
+ // Store the mapping from token ID to ethscription ID
+ tokenIdToEthscriptionId[tokenId] = params.ethscriptionId;
// Mint to initial owner (if address(0), mint to creator then transfer)
if (params.initialOwner == address(0)) {
@@ -242,7 +248,7 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
}
emit EthscriptionCreated(
- params.transactionHash,
+ params.ethscriptionId,
creator,
params.initialOwner,
params.contentUriHash,
@@ -251,20 +257,20 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
);
// Handle protocol operations (if any)
- _callProtocolOperation(params.transactionHash, params.protocolParams);
+ _callProtocolOperation(params.ethscriptionId, params.protocolParams);
}
/// @notice Transfer an ethscription
/// @dev Called via system transaction with msg.sender spoofed as 'from'
/// @param to The recipient address (can be address(0) for burning)
- /// @param transactionHash The ethscription to transfer (used to find token ID)
+ /// @param ethscriptionId The ethscription to transfer (used to find token ID)
function transferEthscription(
address to,
- bytes32 transactionHash
- ) external requireExists(transactionHash) {
- // Get the ethscription number to use as token ID
- Ethscription storage etsc = ethscriptions[transactionHash];
- uint256 tokenId = etsc.ethscriptionNumber;
+ bytes32 ethscriptionId
+ ) external {
+ // Load and validate
+ Ethscription storage ethscription = _getEthscriptionOrRevert(ethscriptionId);
+ uint256 tokenId = ethscription.ethscriptionNumber;
// Standard ERC721 transfer will handle authorization
transferFrom(msg.sender, to, tokenId);
}
@@ -272,39 +278,39 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
/// @notice Transfer an ethscription with previous owner validation (ESIP-2)
/// @dev Called via system transaction with msg.sender spoofed as 'from'
/// @param to The recipient address (can be address(0) for burning)
- /// @param transactionHash The ethscription to transfer
+ /// @param ethscriptionId The ethscription to transfer
/// @param previousOwner The required previous owner for validation
function transferEthscriptionForPreviousOwner(
address to,
- bytes32 transactionHash,
+ bytes32 ethscriptionId,
address previousOwner
- ) external requireExists(transactionHash) {
- Ethscription storage etsc = ethscriptions[transactionHash];
+ ) external {
+ Ethscription storage ethscription = _getEthscriptionOrRevert(ethscriptionId);
// Verify the previous owner matches
- if (etsc.previousOwner != previousOwner) {
+ if (ethscription.previousOwner != previousOwner) {
revert PreviousOwnerMismatch();
}
// Use transferFrom which now handles burns when to == address(0)
- transferFrom(msg.sender, to, etsc.ethscriptionNumber);
+ transferFrom(msg.sender, to, ethscription.ethscriptionNumber);
}
/// @notice Transfer multiple ethscriptions to a single recipient
/// @dev Continues transferring even if individual transfers fail due to wrong ownership
- /// @param transactionHashes Array of ethscription hashes to transfer
+ /// @param ethscriptionIds Array of ethscription IDs to transfer
/// @param to The recipient address (can be address(0) for burning)
/// @return successCount Number of successful transfers
function transferEthscriptions(
address to,
- bytes32[] calldata transactionHashes
+ bytes32[] calldata ethscriptionIds
) external returns (uint256 successCount) {
- for (uint256 i = 0; i < transactionHashes.length; i++) {
+ for (uint256 i = 0; i < ethscriptionIds.length; i++) {
// Get the ethscription to find its token ID
- if (!_ethscriptionExists(transactionHashes[i])) continue; // Skip non-existent ethscriptions
- Ethscription storage etsc = ethscriptions[transactionHashes[i]];
+ if (!_ethscriptionExists(ethscriptionIds[i])) continue; // Skip non-existent ethscriptions
+ Ethscription storage ethscription = ethscriptions[ethscriptionIds[i]];
- uint256 tokenId = etsc.ethscriptionNumber;
+ uint256 tokenId = ethscription.ethscriptionNumber;
// Check if sender owns this token before attempting transfer
// This prevents reverts and allows us to continue
@@ -337,81 +343,108 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
/// @notice Returns the full data URI for a token
function tokenURI(uint256 tokenId) public view override returns (string memory) {
- // Find the transaction hash for this token ID (ethscription number)
- bytes32 txHash = tokenIdToTransactionHash[tokenId];
- if (!_ethscriptionExists(txHash)) revert TokenDoesNotExist();
- Ethscription storage etsc = ethscriptions[txHash];
+ // Find the ethscription for this token ID (ethscription number)
+ Ethscription storage ethscription = _getEthscriptionOrRevert(tokenId);
+ bytes32 id = tokenIdToEthscriptionId[tokenId];
// Get content
- bytes memory content = getEthscriptionContent(txHash);
+ bytes memory content = getEthscriptionContent(id);
// Build complete token URI using the library - it handles everything internally
- return EthscriptionsRendererLib.buildTokenURI(etsc, txHash, content);
+ return EthscriptionsRendererLib.buildTokenURI(ethscription, id, content);
}
/// @notice Get the media URI for an ethscription (image or animation_url)
- /// @param txHash The transaction hash of the ethscription
+ /// @param ethscriptionId The ethscription ID (L1 tx hash) of the ethscription
/// @return mediaType Either "image" or "animation_url"
/// @return mediaUri The data URI for the media
- function getMediaUri(bytes32 txHash) external view requireExists(txHash) returns (string memory mediaType, string memory mediaUri) {
- Ethscription storage etsc = ethscriptions[txHash];
- bytes memory content = getEthscriptionContent(txHash);
- return etsc.getMediaUri(content);
+ function getMediaUri(bytes32 ethscriptionId) external view returns (string memory mediaType, string memory mediaUri) {
+ Ethscription storage ethscription = _getEthscriptionOrRevert(ethscriptionId);
+ bytes memory content = getEthscriptionContent(ethscriptionId);
+ return ethscription.getMediaUri(content);
}
// -------------------- Data Retrieval --------------------
/// @notice Get ethscription details (returns struct to avoid stack too deep)
- function getEthscription(bytes32 transactionHash) external view requireExists(transactionHash) returns (Ethscription memory) {
- return ethscriptions[transactionHash];
+ function getEthscription(bytes32 ethscriptionId) external view returns (Ethscription memory) {
+ return _getEthscriptionOrRevert(ethscriptionId);
}
/// @notice Get content for an ethscription
- function getEthscriptionContent(bytes32 txHash) public view requireExists(txHash) returns (bytes memory) {
- Ethscription storage etsc = ethscriptions[txHash];
- address[] storage pointers = contentPointersBySha[etsc.contentSha];
+ function getEthscriptionContent(bytes32 ethscriptionId) public view returns (bytes memory) {
+ Ethscription storage ethscription = _getEthscriptionOrRevert(ethscriptionId);
+ address[] storage pointers = contentPointersBySha[ethscription.contentSha];
// Empty content is valid - returns "" for empty pointers array
return pointers.read();
}
/// @notice Get ethscription details and content in a single call
- /// @param txHash The transaction hash to look up
+ /// @param ethscriptionId The ethscription ID to look up
/// @return ethscription The ethscription struct
/// @return content The content bytes
- function getEthscriptionWithContent(bytes32 txHash) external view requireExists(txHash) returns (Ethscription memory ethscription, bytes memory content) {
- ethscription = ethscriptions[txHash];
- address[] storage pointers = contentPointersBySha[ethscription.contentSha];
- // Empty content is valid - returns "" for empty pointers array
- content = pointers.read();
+ function getEthscriptionWithContent(bytes32 ethscriptionId) external view returns (Ethscription memory ethscription, bytes memory content) {
+ ethscription = _getEthscriptionOrRevert(ethscriptionId);
+ content = getEthscriptionContent(ethscriptionId);
+ }
+
+ /// @notice Overload: get ethscription by tokenId
+ function getEthscription(uint256 tokenId) external view returns (Ethscription memory) {
+ Ethscription storage ethscription = _getEthscriptionOrRevert(tokenId);
+ return ethscription;
+ }
+
+ /// @notice Overload: get content by tokenId
+ function getEthscriptionContent(uint256 tokenId) external view returns (bytes memory) {
+ // Ensure it exists
+ _getEthscriptionOrRevert(tokenId);
+ bytes32 id = tokenIdToEthscriptionId[tokenId];
+ return getEthscriptionContent(id);
+ }
+
+ /// @notice Overload: get struct and content by tokenId
+ function getEthscriptionWithContent(uint256 tokenId) external view returns (Ethscription memory ethscription, bytes memory content) {
+ ethscription = _getEthscriptionOrRevert(tokenId);
+ bytes32 id = tokenIdToEthscriptionId[tokenId];
+ content = getEthscriptionContent(id);
}
// ---------------- Ownership & Existence Checks ----------------
/// @notice Check if an ethscription exists
- /// @param transactionHash The transaction hash to check
+ /// @param ethscriptionId The ethscription ID to check
/// @return true if the ethscription exists
- function exists(bytes32 transactionHash) external view returns (bool) {
- return _ethscriptionExists(transactionHash);
+ function exists(bytes32 ethscriptionId) external view returns (bool) {
+ return _ethscriptionExists(ethscriptionId);
}
function exists(uint256 tokenId) external view returns (bool) {
- return _ethscriptionExists(tokenIdToTransactionHash[tokenId]);
+ return _ethscriptionExists(tokenIdToEthscriptionId[tokenId]);
}
/// @notice Get owner of an ethscription by transaction hash
/// @dev Overload of ownerOf that accepts transaction hash instead of token ID
- function ownerOf(bytes32 transactionHash) external view requireExists(transactionHash) returns (address) {
- Ethscription storage etsc = ethscriptions[transactionHash];
- uint256 tokenId = etsc.ethscriptionNumber;
+ function ownerOf(bytes32 ethscriptionId) external view returns (address) {
+ Ethscription storage ethscription = _getEthscriptionOrRevert(ethscriptionId);
+ uint256 tokenId = ethscription.ethscriptionNumber;
return ownerOf(tokenId);
}
/// @notice Get the token ID (ethscription number) for a given transaction hash
- /// @param transactionHash The transaction hash to look up
+ /// @param ethscriptionId The ethscription ID to look up
/// @return The token ID (ethscription number)
- function getTokenId(bytes32 transactionHash) external view requireExists(transactionHash) returns (uint256) {
- return ethscriptions[transactionHash].ethscriptionNumber;
+ function getTokenId(bytes32 ethscriptionId) external view returns (uint256) {
+ Ethscription storage ethscription = _getEthscriptionOrRevert(ethscriptionId);
+ return ethscription.ethscriptionNumber;
+ }
+
+ /// @notice Get the ethscription ID (bytes32) for a given tokenId
+ /// @dev Reverts if tokenId does not exist
+ function getEthscriptionId(uint256 tokenId) external view returns (bytes32) {
+ bytes32 id = tokenIdToEthscriptionId[tokenId];
+ if (!_ethscriptionExists(id)) revert TokenDoesNotExist();
+ return id;
}
// =============================================================
@@ -420,41 +453,41 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
/// @dev Override _update to track previous owner and handle token transfers
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address from) {
- // Find the transaction hash for this token ID (ethscription number)
- bytes32 txHash = tokenIdToTransactionHash[tokenId];
- Ethscription storage etsc = ethscriptions[txHash];
+ // Find the ethscription ID for this token ID (ethscription number)
+ bytes32 id = tokenIdToEthscriptionId[tokenId];
+ Ethscription storage ethscription = ethscriptions[id];
// Call parent implementation first to handle the actual update
from = super._update(to, tokenId, auth);
if (from == address(0)) {
// Mint: emit once when minted directly to initial owner
- if (to == etsc.initialOwner) {
- emit EthscriptionTransferred(txHash, etsc.creator, to, tokenId);
+ if (to == ethscription.initialOwner) {
+ emit EthscriptionTransferred(id, ethscription.creator, to, tokenId);
}
// no previousOwner update or tokenManager call on mint
} else {
// Transfers (including creator -> address(0))
- emit EthscriptionTransferred(txHash, from, to, tokenId);
- etsc.previousOwner = from;
+ emit EthscriptionTransferred(id, from, to, tokenId);
+ ethscription.previousOwner = from;
// Notify protocol handler about the transfer if this ethscription has a protocol
- _notifyProtocolTransfer(txHash, from, to);
+ _notifyProtocolTransfer(id, from, to);
}
// Queue ethscription for batch proving at block boundary once proving is live
- _queueForProving(txHash);
+ _queueForProving(id);
}
/// @notice Check if an ethscription exists
/// @dev An ethscription exists if it has been created (has a creator set)
- /// @param transactionHash The transaction hash to check
+ /// @param ethscriptionId The ethscription ID to check
/// @return True if the ethscription exists
- function _ethscriptionExists(bytes32 transactionHash) internal view returns (bool) {
+ function _ethscriptionExists(bytes32 ethscriptionId) internal view returns (bool) {
// Check if this ethscription has been created
// We can't use _tokenExists here because we need the tokenId first
// Instead, check if creator is set (ethscriptions are never created with zero creator)
- return ethscriptions[transactionHash].creator != address(0);
+ return ethscriptions[ethscriptionId].creator != address(0);
}
/// @notice Internal helper to store content and return its SHA
@@ -484,17 +517,17 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
return contentSha;
}
- function _queueForProving(bytes32 txHash) internal {
+ function _queueForProving(bytes32 ethscriptionId) internal {
if (block.timestamp >= Constants.historicalBackfillApproxDoneAt) {
- prover.queueEthscription(txHash);
+ prover.queueEthscription(ethscriptionId);
}
}
/// @notice Call a protocol handler operation during ethscription creation
- /// @param txHash The ethscription transaction hash
+ /// @param ethscriptionId The ethscription ID (L1 tx hash)
/// @param protocolParams The protocol parameters struct
function _callProtocolOperation(
- bytes32 txHash,
+ bytes32 ethscriptionId,
ProtocolParams calldata protocolParams
) internal {
// Skip if no protocol specified
@@ -503,7 +536,7 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
}
// Track which protocol this ethscription uses
- protocolOf[txHash] = protocolParams.protocolName;
+ protocolOf[ethscriptionId] = protocolParams.protocolName;
address handler = protocolHandlers[protocolParams.protocolName];
@@ -515,7 +548,7 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
// Encode the function call with operation name
bytes memory callData = abi.encodeWithSignature(
string.concat("op_", protocolParams.operation, "(bytes32,bytes)"),
- txHash,
+ ethscriptionId,
protocolParams.data
);
@@ -523,22 +556,22 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
(bool success, bytes memory returnData) = handler.call(callData);
if (!success) {
- emit ProtocolHandlerFailed(txHash, protocolParams.protocolName, returnData);
+ emit ProtocolHandlerFailed(ethscriptionId, protocolParams.protocolName, returnData);
} else {
- emit ProtocolHandlerSuccess(txHash, protocolParams.protocolName, returnData);
+ emit ProtocolHandlerSuccess(ethscriptionId, protocolParams.protocolName, returnData);
}
}
/// @notice Notify protocol handler about an ethscription transfer
- /// @param txHash The ethscription transaction hash
+ /// @param ethscriptionId The ethscription ID (L1 tx hash)
/// @param from The address transferring from
/// @param to The address transferring to
function _notifyProtocolTransfer(
- bytes32 txHash,
+ bytes32 ethscriptionId,
address from,
address to
) internal {
- string memory protocol = protocolOf[txHash];
+ string memory protocol = protocolOf[ethscriptionId];
// Skip if no protocol assigned
if (bytes(protocol).length == 0) {
@@ -553,11 +586,11 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
}
// Use try/catch for cleaner error handling
- try IProtocolHandler(handler).onTransfer(txHash, from, to) {
+ try IProtocolHandler(handler).onTransfer(ethscriptionId, from, to) {
// onTransfer doesn't return data, so pass empty bytes
- emit ProtocolHandlerSuccess(txHash, protocol, "");
+ emit ProtocolHandlerSuccess(ethscriptionId, protocol, "");
} catch (bytes memory revertData) {
- emit ProtocolHandlerFailed(txHash, protocol, revertData);
+ emit ProtocolHandlerFailed(ethscriptionId, protocol, revertData);
}
}
@@ -573,48 +606,48 @@ contract Ethscriptions is ERC721EthscriptionsUpgradeable {
// Emit events in the order they were created (FIFO)
for (uint256 i = 0; i < count; i++) {
- bytes32 txHash = pendingGenesisEvents[i];
+ bytes32 ethscriptionId = pendingGenesisEvents[i];
// Get the ethscription data
- Ethscription storage etsc = ethscriptions[txHash];
- uint256 tokenId = etsc.ethscriptionNumber;
+ Ethscription storage ethscription = ethscriptions[ethscriptionId];
+ uint256 tokenId = ethscription.ethscriptionNumber;
// Emit events in the same order as live mints:
// 1. Transfer (mint), 2. EthscriptionTransferred, 3. EthscriptionCreated
- if (etsc.initialOwner == address(0)) {
+ if (ethscription.initialOwner == address(0)) {
// Token was minted to creator then burned
// First emit mint to creator
- emit Transfer(address(0), etsc.creator, tokenId);
+ emit Transfer(address(0), ethscription.creator, tokenId);
// Then emit burn from creator to null address
- emit Transfer(etsc.creator, address(0), tokenId);
+ emit Transfer(ethscription.creator, address(0), tokenId);
// Emit Ethscriptions transfer event for the burn
emit EthscriptionTransferred(
- txHash,
- etsc.creator,
+ ethscriptionId,
+ ethscription.creator,
address(0),
- etsc.ethscriptionNumber
+ ethscription.ethscriptionNumber
);
} else {
// Token was minted directly to initial owner
- emit Transfer(address(0), etsc.initialOwner, tokenId);
+ emit Transfer(address(0), ethscription.initialOwner, tokenId);
// Emit Ethscriptions transfer event
emit EthscriptionTransferred(
- txHash,
- etsc.creator,
- etsc.initialOwner,
- etsc.ethscriptionNumber
+ ethscriptionId,
+ ethscription.creator,
+ ethscription.initialOwner,
+ ethscription.ethscriptionNumber
);
}
// Finally emit the creation event (matching the order of live mints)
emit EthscriptionCreated(
- txHash,
- etsc.creator,
- etsc.initialOwner,
- etsc.contentUriHash,
- etsc.contentSha,
- etsc.ethscriptionNumber
+ ethscriptionId,
+ ethscription.creator,
+ ethscription.initialOwner,
+ ethscription.contentUriHash,
+ ethscription.contentSha,
+ ethscription.ethscriptionNumber
);
}
diff --git a/contracts/src/EthscriptionsERC20.sol b/contracts/src/EthscriptionsERC20.sol
index 25afc47..7a4bf6a 100644
--- a/contracts/src/EthscriptionsERC20.sol
+++ b/contracts/src/EthscriptionsERC20.sol
@@ -20,8 +20,8 @@ contract EthscriptionsERC20 is ERC20NullOwnerCappedUpgradeable {
// STATE VARIABLES
// =============================================================
- /// @notice The ethscription hash that deployed this token
- bytes32 public deployTxHash;
+ /// @notice The ethscription ID that deployed this token
+ bytes32 public deployEthscriptionId;
// =============================================================
// CUSTOM ERRORS
@@ -48,16 +48,16 @@ contract EthscriptionsERC20 is ERC20NullOwnerCappedUpgradeable {
/// @param name_ The token name
/// @param symbol_ The token symbol
/// @param cap_ The maximum supply cap (in 18 decimals)
- /// @param deployTxHash_ The ethscription hash that deployed this token
+ /// @param deployEthscriptionId_ The ethscription ID that deployed this token
function initialize(
string memory name_,
string memory symbol_,
uint256 cap_,
- bytes32 deployTxHash_
+ bytes32 deployEthscriptionId_
) external initializer {
__ERC20_init(name_, symbol_);
__ERC20Capped_init(cap_);
- deployTxHash = deployTxHash_;
+ deployEthscriptionId = deployEthscriptionId_;
}
/// @notice Mint tokens (TokenManager only)
@@ -98,4 +98,4 @@ contract EthscriptionsERC20 is ERC20NullOwnerCappedUpgradeable {
function approve(address, uint256) public pure override returns (bool) {
revert ApprovalsNotAllowed();
}
-}
\ No newline at end of file
+}
diff --git a/contracts/src/EthscriptionsProver.sol b/contracts/src/EthscriptionsProver.sol
index 09acd17..5346520 100644
--- a/contracts/src/EthscriptionsProver.sol
+++ b/contracts/src/EthscriptionsProver.sol
@@ -27,7 +27,7 @@ contract EthscriptionsProver {
/// @notice Struct for ethscription data proof
struct EthscriptionDataProof {
- bytes32 ethscriptionTxHash;
+ bytes32 ethscriptionId;
bytes32 contentSha;
bytes32 contentUriHash;
bytes32 l1BlockHash;
@@ -78,7 +78,7 @@ contract EthscriptionsProver {
/// @notice Emitted when an ethscription data proof is sent to L1
event EthscriptionDataProofSent(
- bytes32 indexed ethscriptionTxHash,
+ bytes32 indexed ethscriptionId,
uint256 indexed l2BlockNumber,
uint256 l2Timestamp
);
@@ -89,16 +89,16 @@ contract EthscriptionsProver {
/// @notice Queue an ethscription for proving
/// @dev Only callable by the Ethscriptions contract
- /// @param txHash The transaction hash of the ethscription
- function queueEthscription(bytes32 txHash) external virtual {
+ /// @param ethscriptionId The ID of the ethscription (L1 tx hash)
+ function queueEthscription(bytes32 ethscriptionId) external virtual {
if (msg.sender != address(ethscriptions)) revert OnlyEthscriptions();
// Add to the set (deduplicates automatically)
- if (queuedEthscriptions.add(txHash)) {
- // Only store info if this is the first time we're queueing this txHash
+ if (queuedEthscriptions.add(ethscriptionId)) {
+ // Only store info if this is the first time we're queueing this ID
// Capture the L1 block hash and number at the time of queuing
L1Block l1Block = L1Block(L1_BLOCK);
- queuedProofInfo[txHash] = QueuedProof({
+ queuedProofInfo[ethscriptionId] = QueuedProof({
l1BlockHash: l1Block.hash(),
l2BlockNumber: uint48(block.number),
l2BlockTimestamp: uint48(block.timestamp),
@@ -117,14 +117,14 @@ contract EthscriptionsProver {
// Process and remove each ethscription from the set
// We iterate backwards to avoid index shifting during removal
for (uint256 i = count; i > 0; i--) {
- bytes32 txHash = queuedEthscriptions.at(i - 1);
+ bytes32 ethscriptionId = queuedEthscriptions.at(i - 1);
// Create and send proof for current state with stored block info
- _createAndSendProof(txHash, queuedProofInfo[txHash]);
+ _createAndSendProof(ethscriptionId, queuedProofInfo[ethscriptionId]);
// Clean up: remove from set and delete the proof info
- queuedEthscriptions.remove(txHash);
- delete queuedProofInfo[txHash];
+ queuedEthscriptions.remove(ethscriptionId);
+ delete queuedProofInfo[ethscriptionId];
}
}
@@ -133,24 +133,24 @@ contract EthscriptionsProver {
// =============================================================
/// @notice Internal function to create and send proof for an ethscription
- /// @param ethscriptionTxHash The transaction hash of the ethscription
+ /// @param ethscriptionId The Ethscription ID (L1 tx hash)
/// @param proofInfo The queued proof info containing block data
- function _createAndSendProof(bytes32 ethscriptionTxHash, QueuedProof memory proofInfo) internal {
+ function _createAndSendProof(bytes32 ethscriptionId, QueuedProof memory proofInfo) internal {
// Get ethscription data including previous owner
- Ethscriptions.Ethscription memory etsc = ethscriptions.getEthscription(ethscriptionTxHash);
- address currentOwner = ethscriptions.ownerOf(ethscriptionTxHash);
+ Ethscriptions.Ethscription memory ethscription = ethscriptions.getEthscription(ethscriptionId);
+ address currentOwner = ethscriptions.ownerOf(ethscriptionId);
// Create proof struct with all ethscription data
EthscriptionDataProof memory proof = EthscriptionDataProof({
- ethscriptionTxHash: ethscriptionTxHash,
- contentSha: etsc.contentSha,
- contentUriHash: etsc.contentUriHash,
+ ethscriptionId: ethscriptionId,
+ contentSha: ethscription.contentSha,
+ contentUriHash: ethscription.contentUriHash,
l1BlockHash: proofInfo.l1BlockHash,
- creator: etsc.creator,
+ creator: ethscription.creator,
currentOwner: currentOwner,
- previousOwner: etsc.previousOwner,
- esip6: etsc.esip6,
- ethscriptionNumber: etsc.ethscriptionNumber,
+ previousOwner: ethscription.previousOwner,
+ esip6: ethscription.esip6,
+ ethscriptionNumber: ethscription.ethscriptionNumber,
l1BlockNumber: proofInfo.l1BlockNumber,
l2BlockNumber: proofInfo.l2BlockNumber,
l2Timestamp: proofInfo.l2BlockTimestamp
@@ -160,6 +160,6 @@ contract EthscriptionsProver {
bytes memory proofData = abi.encode(proof);
L2_TO_L1_MESSAGE_PASSER.initiateWithdrawal(address(0), 0, proofData);
- emit EthscriptionDataProofSent(ethscriptionTxHash, proofInfo.l2BlockNumber, proofInfo.l2BlockTimestamp);
+ emit EthscriptionDataProofSent(ethscriptionId, proofInfo.l2BlockNumber, proofInfo.l2BlockTimestamp);
}
-}
\ No newline at end of file
+}
diff --git a/contracts/src/TokenManager.sol b/contracts/src/TokenManager.sol
index 0f582ab..da23a31 100644
--- a/contracts/src/TokenManager.sol
+++ b/contracts/src/TokenManager.sol
@@ -21,7 +21,7 @@ contract TokenManager is IProtocolHandler {
struct TokenInfo {
address tokenContract;
- bytes32 deployTxHash;
+ bytes32 deployEthscriptionId;
string tick;
uint256 maxSupply;
uint256 mintAmount;
@@ -29,8 +29,8 @@ contract TokenManager is IProtocolHandler {
}
struct TokenItem {
- bytes32 deployTxHash; // Which token this ethscription belongs to
- uint256 amount; // How many tokens this ethscription represents
+ bytes32 deployEthscriptionId; // Which token this ethscription belongs to
+ uint256 amount; // How many tokens this ethscription represents
}
// Protocol operation structs for cleaner decoding
@@ -60,8 +60,8 @@ contract TokenManager is IProtocolHandler {
/// @dev Track deployed tokens by protocol+tick for find-or-create
mapping(bytes32 => TokenInfo) internal tokensByTick; // keccak256(abi.encode(protocol, tick)) => TokenInfo
- /// @dev Map deploy transaction hash to tick key for lookups
- mapping(bytes32 => bytes32) public deployToTick; // deployTxHash => tickKey
+ /// @dev Map deploy ethscription ID to tick key for lookups
+ mapping(bytes32 => bytes32) public deployToTick; // deployEthscriptionId => tickKey
/// @dev Track which ethscription is a token item
mapping(bytes32 => TokenItem) internal tokenItems; // ethscription tx hash => TokenItem
@@ -84,7 +84,7 @@ contract TokenManager is IProtocolHandler {
// =============================================================
event TokenDeployed(
- bytes32 indexed deployTxHash,
+ bytes32 indexed deployEthscriptionId,
address indexed tokenAddress,
string tick,
uint256 maxSupply,
@@ -92,18 +92,18 @@ contract TokenManager is IProtocolHandler {
);
event TokenMinted(
- bytes32 indexed deployTxHash,
+ bytes32 indexed deployEthscriptionId,
address indexed to,
uint256 amount,
- bytes32 ethscriptionTxHash
+ bytes32 ethscriptionId
);
event TokenTransferred(
- bytes32 indexed deployTxHash,
+ bytes32 indexed deployEthscriptionId,
address indexed from,
address indexed to,
uint256 amount,
- bytes32 ethscriptionTxHash
+ bytes32 ethscriptionId
);
// =============================================================
@@ -120,9 +120,9 @@ contract TokenManager is IProtocolHandler {
// =============================================================
/// @notice Handle deploy operation
- /// @param txHash The ethscription transaction hash
+ /// @param ethscriptionId The ethscription ID
/// @param data The encoded DeployOperation data
- function op_deploy(bytes32 txHash, bytes calldata data) external virtual onlyEthscriptions {
+ function op_deploy(bytes32 ethscriptionId, bytes calldata data) external virtual onlyEthscriptions {
// Decode the operation data
DeployOperation memory deployOp = abi.decode(data, (DeployOperation));
@@ -130,7 +130,7 @@ contract TokenManager is IProtocolHandler {
TokenInfo storage token = tokensByTick[tickKey];
// Revert if token already exists
- if (token.deployTxHash != bytes32(0)) revert TokenAlreadyDeployed();
+ if (token.deployEthscriptionId != bytes32(0)) revert TokenAlreadyDeployed();
// Validate deployment parameters
if (deployOp.maxSupply == 0) revert InvalidMaxSupply();
@@ -150,29 +150,29 @@ contract TokenManager is IProtocolHandler {
name,
symbol,
deployOp.maxSupply * 10**18,
- txHash
+ ethscriptionId
);
// Store token info
tokensByTick[tickKey] = TokenInfo({
tokenContract: tokenAddress,
- deployTxHash: txHash,
+ deployEthscriptionId: ethscriptionId,
tick: deployOp.tick,
maxSupply: deployOp.maxSupply,
mintAmount: deployOp.mintAmount,
totalMinted: 0
});
- // Map deploy hash to tick key for lookups
- deployToTick[txHash] = tickKey;
+ // Map deploy ID to tick key for lookups
+ deployToTick[ethscriptionId] = tickKey;
- emit TokenDeployed(txHash, tokenAddress, deployOp.tick, deployOp.maxSupply, deployOp.mintAmount);
+ emit TokenDeployed(ethscriptionId, tokenAddress, deployOp.tick, deployOp.maxSupply, deployOp.mintAmount);
}
/// @notice Handle mint operation
- /// @param txHash The ethscription transaction hash
+ /// @param ethscriptionId The ethscription ID
/// @param data The encoded MintOperation data
- function op_mint(bytes32 txHash, bytes calldata data) external virtual onlyEthscriptions {
+ function op_mint(bytes32 ethscriptionId, bytes calldata data) external virtual onlyEthscriptions {
// Decode the operation data
MintOperation memory mintOp = abi.decode(data, (MintOperation));
@@ -180,7 +180,7 @@ contract TokenManager is IProtocolHandler {
TokenInfo storage token = tokensByTick[tickKey];
// Token must exist to mint
- if (token.deployTxHash == bytes32(0)) revert TokenNotDeployed();
+ if (token.deployEthscriptionId == bytes32(0)) revert TokenNotDeployed();
// Validate mint amount matches token's configured limit
if (mintOp.amount != token.mintAmount) revert MintAmountMismatch();
@@ -192,12 +192,12 @@ contract TokenManager is IProtocolHandler {
// Get the initial owner from the Ethscriptions contract
Ethscriptions ethscriptionsContract = Ethscriptions(ethscriptions);
- Ethscriptions.Ethscription memory ethscription = ethscriptionsContract.getEthscription(txHash);
+ Ethscriptions.Ethscription memory ethscription = ethscriptionsContract.getEthscription(ethscriptionId);
address initialOwner = ethscription.initialOwner;
// Track this ethscription as a token item
- tokenItems[txHash] = TokenItem({
- deployTxHash: token.deployTxHash,
+ tokenItems[ethscriptionId] = TokenItem({
+ deployEthscriptionId: token.deployEthscriptionId,
amount: mintOp.amount
});
@@ -207,42 +207,42 @@ contract TokenManager is IProtocolHandler {
// Update total minted after successful mint
token.totalMinted += mintOp.amount;
- emit TokenMinted(token.deployTxHash, initialOwner, mintOp.amount, txHash);
+ emit TokenMinted(token.deployEthscriptionId, initialOwner, mintOp.amount, ethscriptionId);
}
/// @notice Handle transfer notification from Ethscriptions contract
/// @dev Implementation of IProtocolHandler interface
- /// @param txHash The ethscription transaction hash being transferred
+ /// @param ethscriptionId The ethscription ID being transferred
/// @param from The address transferring from
/// @param to The address transferring to
function onTransfer(
- bytes32 txHash,
+ bytes32 ethscriptionId,
address from,
address to
) external virtual override onlyEthscriptions {
- TokenItem memory item = tokenItems[txHash];
+ TokenItem memory item = tokenItems[ethscriptionId];
// Not a token item, nothing to do
- if (item.deployTxHash == bytes32(0)) return;
+ if (item.deployEthscriptionId == bytes32(0)) return;
- bytes32 tickKey = deployToTick[item.deployTxHash];
+ bytes32 tickKey = deployToTick[item.deployEthscriptionId];
TokenInfo storage token = tokensByTick[tickKey];
// Force transfer tokens (shadow transfer) - convert to 18 decimals
EthscriptionsERC20(token.tokenContract).forceTransfer(from, to, item.amount * 10**18);
- emit TokenTransferred(item.deployTxHash, from, to, item.amount, txHash);
+ emit TokenTransferred(item.deployEthscriptionId, from, to, item.amount, ethscriptionId);
}
// =============================================================
// EXTERNAL VIEW FUNCTIONS
// =============================================================
- /// @notice Get token contract address by deploy transaction hash
- /// @param deployTxHash The deployment transaction hash
+ /// @notice Get token contract address by deploy ethscription ID
+ /// @param deployEthscriptionId The deployment ethscription ID
/// @return The token contract address
- function getTokenAddress(bytes32 deployTxHash) external view returns (address) {
- bytes32 tickKey = deployToTick[deployTxHash];
+ function getTokenAddress(bytes32 deployEthscriptionId) external view returns (address) {
+ bytes32 tickKey = deployToTick[deployEthscriptionId];
return tokensByTick[tickKey].tokenContract;
}
@@ -254,11 +254,11 @@ contract TokenManager is IProtocolHandler {
return tokensByTick[tickKey].tokenContract;
}
- /// @notice Get complete token information by deploy transaction hash
- /// @param deployTxHash The deployment transaction hash
+ /// @notice Get complete token information by deploy ethscription ID
+ /// @param deployEthscriptionId The deployment ethscription ID
/// @return The TokenInfo struct
- function getTokenInfo(bytes32 deployTxHash) external view returns (TokenInfo memory) {
- bytes32 tickKey = deployToTick[deployTxHash];
+ function getTokenInfo(bytes32 deployEthscriptionId) external view returns (TokenInfo memory) {
+ bytes32 tickKey = deployToTick[deployEthscriptionId];
return tokensByTick[tickKey];
}
@@ -286,24 +286,24 @@ contract TokenManager is IProtocolHandler {
}
/// @notice Check if an ethscription is a token item
- /// @param ethscriptionTxHash The ethscription transaction hash
+ /// @param ethscriptionId The ethscription ID
/// @return True if the ethscription represents tokens
- function isTokenItem(bytes32 ethscriptionTxHash) external view returns (bool) {
- return tokenItems[ethscriptionTxHash].deployTxHash != bytes32(0);
+ function isTokenItem(bytes32 ethscriptionId) external view returns (bool) {
+ return tokenItems[ethscriptionId].deployEthscriptionId != bytes32(0);
}
/// @notice Get token amount for an ethscription
- /// @param ethscriptionTxHash The ethscription transaction hash
+ /// @param ethscriptionId The ethscription ID
/// @return The amount of tokens this ethscription represents
- function getTokenAmount(bytes32 ethscriptionTxHash) external view returns (uint256) {
- return tokenItems[ethscriptionTxHash].amount;
+ function getTokenAmount(bytes32 ethscriptionId) external view returns (uint256) {
+ return tokenItems[ethscriptionId].amount;
}
/// @notice Get complete token item information
- /// @param ethscriptionTxHash The ethscription transaction hash
+ /// @param ethscriptionId The ethscription ID
/// @return The TokenItem struct
- function getTokenItem(bytes32 ethscriptionTxHash) external view returns (TokenItem memory) {
- return tokenItems[ethscriptionTxHash];
+ function getTokenItem(bytes32 ethscriptionId) external view returns (TokenItem memory) {
+ return tokenItems[ethscriptionId];
}
// =============================================================
@@ -327,4 +327,4 @@ contract TokenManager is IProtocolHandler {
// Use the protocol name from this handler
return keccak256(abi.encode("erc-20", tick));
}
-}
\ No newline at end of file
+}
diff --git a/contracts/src/interfaces/IProtocolHandler.sol b/contracts/src/interfaces/IProtocolHandler.sol
index 2525452..a1bdbf0 100644
--- a/contracts/src/interfaces/IProtocolHandler.sol
+++ b/contracts/src/interfaces/IProtocolHandler.sol
@@ -6,11 +6,11 @@ pragma solidity 0.8.24;
/// @dev Handlers process protocol-specific logic for Ethscriptions lifecycle events
interface IProtocolHandler {
/// @notice Called when an Ethscription with this protocol is transferred
- /// @param txHash The transaction hash (Ethscription ID)
+ /// @param ethscriptionId The Ethscription ID (L1 tx hash)
/// @param from The address transferring the Ethscription
/// @param to The address receiving the Ethscription
function onTransfer(
- bytes32 txHash,
+ bytes32 ethscriptionId,
address from,
address to
) external;
diff --git a/contracts/src/libraries/EthscriptionsRendererLib.sol b/contracts/src/libraries/EthscriptionsRendererLib.sol
index f855689..4a8a067 100644
--- a/contracts/src/libraries/EthscriptionsRendererLib.sol
+++ b/contracts/src/libraries/EthscriptionsRendererLib.sol
@@ -13,17 +13,17 @@ library EthscriptionsRendererLib {
/// @notice Build attributes JSON array from ethscription data
/// @param etsc Storage pointer to the ethscription
- /// @param txHash The transaction hash of the ethscription
+ /// @param ethscriptionId The ethscription ID (L1 tx hash)
/// @return JSON string of attributes array
- function buildAttributes(Ethscriptions.Ethscription storage etsc, bytes32 txHash)
+ function buildAttributes(Ethscriptions.Ethscription storage etsc, bytes32 ethscriptionId)
internal
view
returns (string memory)
{
// Build in chunks to avoid stack too deep
string memory part1 = string.concat(
- '[{"trait_type":"Transaction Hash","value":"',
- uint256(txHash).toHexString(),
+ '[{"trait_type":"Ethscription ID","value":"',
+ uint256(ethscriptionId).toHexString(),
'"},{"trait_type":"Ethscription Number","display_type":"number","value":',
etsc.ethscriptionNumber.toString(),
'},{"trait_type":"Creator","value":"',
@@ -84,19 +84,19 @@ library EthscriptionsRendererLib {
/// @notice Build complete token URI JSON
/// @param etsc Storage pointer to the ethscription
- /// @param txHash The transaction hash of the ethscription
+ /// @param ethscriptionId The ethscription ID (L1 tx hash)
/// @param content The content bytes
/// @return The complete base64-encoded data URI
function buildTokenURI(
Ethscriptions.Ethscription storage etsc,
- bytes32 txHash,
+ bytes32 ethscriptionId,
bytes memory content
) internal view returns (string memory) {
// Get media URI
(string memory mediaType, string memory mediaUri) = getMediaUri(etsc, content);
// Build attributes
- string memory attributes = buildAttributes(etsc, txHash);
+ string memory attributes = buildAttributes(etsc, ethscriptionId);
// Build JSON
string memory json = string.concat(
@@ -198,4 +198,4 @@ library EthscriptionsRendererLib {
'