How it works · Try it · What is tested · Known issues
This demo shows how a token can control access to private data without putting that data on-chain. The contract stores only a hash of the data and a link to an encrypted copy kept elsewhere. Sell or transfer the token, and the right to access moves with it.
Caution
Gating a function does not hide anything. private in Solidity only stops other contracts from reading a variable, and anyone can read the hash and the link from chain state. A test in this repo does that. Privacy depends on the encryption and on your off-chain service, which must check the token before handing over the decryption key. This contract has not been audited.
flowchart LR
H[Token holder] -->|asks for the key, signs a fresh challenge| S[Your off-chain service]
S -->|balanceOf: holds the token?| C[PrivateAccessToken]
S -->|decryption key| H
H -->|fetches| E[Encrypted copy off-chain]
H -->|verifyData: right document?| C
Your service must check a signature over a fresh random challenge before it reads balanceOf. balanceOf only shows what an address holds, and anyone can claim to be that address.
| Function | What it does |
|---|---|
constructor(dataHash, encryptedDataURI, uri) |
Stores the hash and link, and mints the access token to the deployer |
ViewData() |
Returns the hash and link to the token holder |
verifyData(hash) |
Tells anyone whether a hash matches the stored one |
ViewStatus() |
Returns the caller's token balance |
Add a random salt to what you hash. A hash of predictable data can be guessed.
The off-chain service and the encryption are not part of this repo. You need to build them.
git clone https://github.com/CoinClubQuincy/PrivateAccessToken.git
cd PrivateAccessToken
git clone --depth 1 -b v4.9.6 https://github.com/OpenZeppelin/openzeppelin-contracts lib/openzeppelin-contracts
git clone --depth 1 -b v1.9.7 https://github.com/foundry-rs/forge-std lib/forge-std
forge testYou need Foundry.
test/foundry/PrivateAccessToken.t.sol has 7 tests and runs in CI on every push. They show holders can call ViewData, others are refused, access moves with the token, anyone can verify a hash, and the stored hash can be read from storage without the token. It has not been run on a real network or audited.
Contracts already deployed are unaffected. Anything an earlier deployment stored can still be read from the chain, and it cannot be removed.
- The constructor takes a data hash and an encrypted data link instead of the data itself.
ViewDatareturns those two values.verifyDatais new.- The older Truffle test was removed. Foundry is the supported test path.
| Issue | Effect | Test |
|---|---|---|
| The hash and link are public | Anyone can read them without the token, so the link must only ever point to encrypted data | test_TheStoredHashIsReadableWithoutTheToken |
| Selling the token does not revoke a key | A past holder who already has the decryption key can still read the data. Encrypt again with a new key if that matters | Read from the code |
More XDC and EVM projects
| Group | Project | What it is |
|---|---|---|
| Standards | XRC-SHARES | Dividend-paying NFT shares and SPLITS for a DApp |
| Standards | XRCDividendPlus | Dividend-paying XRC-20 token |
| Treasury and finance | Multi-Sig-Treasury | Treasury controlled by tokenized keys |
| Treasury and finance | XRC-Airdrop | Self-run token airdrop |
| Treasury and finance | XRC-Credit | Single-loan credit contract |
| Treasury and finance | XDC-Defi-Instruments | Assets, agreements, forwards, futures and a marketplace |
| Treasury and finance | XRC1155-Equities-Market | Shares, portfolios and a marketplace on ERC-1155 |
| Treasury and finance | NFTOTC | Over-the-counter sale of a token collection |
| Treasury and finance | DAppProxySwap | Currency swaps for a DApp through a fixed router |
| Identity and access | LoginMFAContract | Login with an NFT and a signed second factor |
| Identity and access | Delegated_Authority | KYC notary proof of concept |
| Identity and access | EncryptedNFT-Documents | NFTs tied to encrypted off-chain documents |
| Learning and libraries | XDC-LemonadeStand | Workshop DApp built on XRC-SHARES |
| Learning and libraries | Non-Financial-SmartContracts | Games, inventory, keys and on-chain repositories |
| Learning and libraries | ContractLedger | On-chain list of contract addresses |
| Learning and libraries | TimestampConverter | Timestamps to calendar dates in Solidity |
| Tools | XDC_Python_SDK_V1 | Python client for the XDC JSON-RPC API |
| Tools | PrivateXDCNode_SetupScript | Private XDC network setup scripts |
| Tools | WebApp_to_XDCPay | Working web app connected to XDCPay |
| Multi-chain | CoinClub_Framework | Python library with an XDC adapter |
| Interfaces | Contract_Interface_Model_Language | Interface documents for smart contracts and APIs |
MIT.
