Fine, here’s a clean, professional, README-ready version that won’t embarrass you when Prof. Aazam opens your repo.
It’s crisp, formatted, structured, and actually readable.
Paste this straight into your README.md.
A blockchain-based provenance system for documenting and validating Qatari Sadu cultural artifacts. This project combines role-based validation, decentralized storage references, and a minimal UI prototype for creators and institutional validators.
Private keys and sensitive values are excluded for security.
The following contracts are currently deployed on the Sepolia testnet:
REGISTRY_ADDRESS = 0x8AC07001FC2d4eEf98f19AD70D66b88085530426
LICENSE_ADDRESS = <your-latest-license-address>
Qatar Museums (QM): 0x99ACCaf6f29bdEDad6BB058E70223Eb76dCCaC33
Ministry of Culture (MoC): 0x368EefF6277abC2A5D6E70e57294C7DA650365aa
Role assignments use OpenZeppelin AccessControl:
- DEFAULT_ADMIN_ROLE → Deployment admin
- QM_VALIDATOR → Qatar Museums
- MOC_VALIDATOR → Ministry of Culture
(Admin only — private keys stored locally in .env)
cast send 0x8AC07001FC2d4eEf98f19AD70D66b88085530426 \
"grantRole(bytes32,address)" \
$(cast keccak "QM_VALIDATOR") \
0x99ACCaf6f29bdEDad6BB058E70223Eb76dCCaC33 \
--private-key $PRIVATE_KEY \
--rpc-url https://ethereum-sepolia.publicnode.comcast send 0x8AC07001FC2d4eEf98f19AD70D66b88085530426 \
"grantRole(bytes32,address)" \
$(cast keccak "MOC_VALIDATOR") \
0x368EefF6277abC2A5D6E70e57294C7DA650365aa \
--private-key $PRIVATE_KEY \
--rpc-url https://ethereum-sepolia.publicnode.comcast call 0x8AC07001FC2d4eEf98f19AD70D66b88085530426 \
"hasRole(bytes32,address)(bool)" \
$(cast keccak "QM_VALIDATOR") \
0x99ACCaf6f29bdEDad6BB058E70223Eb76dCCaC33 \
--rpc-url https://ethereum-sepolia.publicnode.comcast call 0x8AC07001FC2d4eEf98f19AD70D66b88085530426 \
"hasRole(bytes32,address)(bool)" \
$(cast keccak "MOC_VALIDATOR") \
0x368EefF6277abC2A5D6E70e57294C7DA650365aa \
--rpc-url https://ethereum-sepolia.publicnode.comExpected output:
true
These are the commands actually used to deploy, test, debug, generate metrics, and run the UI for Sprint 3 requirements.
Deploy the full Athar system:
forge script script/DeployAthar.s.sol:DeployAthar \
--rpc-url $SEPOLIA_RPC_URL \
--broadcast \
--private-key $PRIVATE_KEY(Executed 3× to gather latency metrics)
forge script script/HappyPath.s.sol:HappyPath \
--rpc-url $SEPOLIA_RPC_URL \
--broadcast \
--private-key $PRIVATE_KEYRun smart contract tests
forge testGenerate coverage summary
forge coverage > sprint3evidence/coverage-summary.txtGenerate gas report
forge snapshot > sprint3evidence/gas-snapshot.txtCheck next artifact ID:
cast call <REGISTRY_ADDRESS> "nextId()(uint256)" --rpc-url $SEPOLIA_RPC_URLFetch artifact struct:
cast call <REGISTRY_ADDRESS> \
"artifacts(uint256)(address,string,bool,bool,bool,bool,bool,string,string,uint256)" \
<id> \
--rpc-url $SEPOLIA_RPC_URLManual validator approval:
cast send <REGISTRY_ADDRESS> "approve(uint256)" <id> \
--private-key $VALIDATOR_PK \
--rpc-url $SEPOLIA_RPC_URLManual reject:
cast send <REGISTRY_ADDRESS> "reject(uint256,string)" <id> "Invalid metadata" \
--private-key $VALIDATOR_PK \
--rpc-url $SEPOLIA_RPC_URLServe UI locally:
python3 -m http.server 8080Open:
http://localhost:8080/frontend/index.html
Foundry contains four main tools:
- Forge – testing, deployment, gas analysis
- Cast – low-level EVM interaction
forge build
forge fmt
forge snapshot
cast <command>