Digital Art Authenticity Contract
What it does:
Provides immutable, on-chain proof of authenticity and provenance for digital artworks, allowing anyone to verify the original creator and ownership history.
Why it matters:
Prevents forgery and plagiarism in digital art, strengthens collector confidence, preserves artist attribution, and creates a verifiable source of truth for digital art markets.
How it works:
-
Artists register an artwork by submitting a cryptographic hash and metadata reference
-
Smart contract permanently links the artwork to the artist’s wallet address
-
Blockchain timestamps establish the moment of creation or registration
-
Ownership transfers are recorded on-chain to build full provenance history
-
No artwork files are stored on-chain, preserving privacy and scalability
-
Anyone can verify authenticity by comparing the artwork hash with on-chain records
-
Integrates seamlessly with NFTs, marketplaces, galleries, and metaverse platforms
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title DigitalArtAuthenticity
* @author Nam
* @notice On-chain authenticity and provenance tracking for digital artworks
*/
contract DigitalArtAuthenticity {
uint256 public artworkCount;
// -------------------- STRUCTS --------------------
struct Artwork {
bytes32 artHash; // Hash of the artwork file
string metadataURI; // IPFS / Arweave metadata
address creator;
address currentOwner;
uint256 createdAt;
uint256 lastTransferAt;
}
struct TransferRecord {
address from;
address to;
uint256 timestamp;
}
// -------------------- STORAGE --------------------
mapping(uint256 => Artwork) public artworks;
mapping(bytes32 => bool) public registeredHashes;
mapping(uint256 => TransferRecord[]) public provenance;
// -------------------- EVENTS --------------------
event ArtworkRegistered(
uint256 indexed artworkId,
bytes32 indexed artHash,
address indexed creator
);
event OwnershipTransferred(
uint256 indexed artworkId,
address indexed from,
address indexed to
);
// -------------------- ART REGISTRATION --------------------
function registerArtwork(bytes32 _artHash, string calldata _metadataURI)
external
returns (uint256)
{
require(_artHash != bytes32(0), "Invalid hash");
require(!registeredHashes[_artHash], "Artwork already registered");
artworkCount += 1;
artworks[artworkCount] = Artwork({
artHash: _artHash,
metadataURI: _metadataURI,
creator: msg.sender,
currentOwner: msg.sender,
createdAt: block.timestamp,
lastTransferAt: block.timestamp
});
registeredHashes[_artHash] = true;
provenance[artworkCount].push(
TransferRecord({
from: address(0),
to: msg.sender,
timestamp: block.timestamp
})
);
emit ArtworkRegistered(artworkCount, _artHash, msg.sender);
return artworkCount;
}
// -------------------- OWNERSHIP TRANSFER --------------------
function transferOwnership(uint256 _artworkId, address _to) external {
Artwork storage art = artworks[_artworkId];
require(msg.sender == art.currentOwner, "Not owner");
require(_to != address(0), "Invalid recipient");
address previousOwner = art.currentOwner;
art.currentOwner = _to;
art.lastTransferAt = block.timestamp;
provenance[_artworkId].push(
TransferRecord({
from: previousOwner,
to: _to,
timestamp: block.timestamp
})
);
emit OwnershipTransferred(_artworkId, previousOwner, _to);
}
// -------------------- VERIFICATION --------------------
function verifyArtwork(bytes32 _artHash)
external
view
returns (
uint256 artworkId,
address creator,
address currentOwner,
uint256 createdAt
)
{
for (uint256 i = 1; i <= artworkCount; i++) {
if (artworks[i].artHash == _artHash) {
Artwork memory art = artworks[i];
return (
i,
art.creator,
art.currentOwner,
art.createdAt
);
}
}
revert("Artwork not found");
}
function getProvenance(uint256 _artworkId)
external
view
returns (TransferRecord[] memory)
{
return provenance[_artworkId];
}
}