contract VoteRevealer is ZamaEthereumConfig { euint32 private _yesVotes; euint32 private _noVotes; bool public isPubliclyDecryptable; function makePublic() external { require(!isPubliclyDecryptable, "Already revealed"); FHE.makePubliclyDecryptable(_yesVotes); FHE.makePubliclyDecryptable(_noVotes); isPubliclyDecryptable = true; }}
Irreversible:FHE.makePubliclyDecryptable() is permanent. Once a value is marked for public decryption, it cannot be made private again.Only use this for:
contract PublicDecrypt is ZamaEthereumConfig { euint32 private _encryptedValue; bool public hasValue; bool public isPubliclyDecryptable; // Store a value — grant ACL to sender (user-specific decrypt) function setValue(uint32 value) external { _encryptedValue = FHE.asEuint32(value); FHE.allowThis(_encryptedValue); FHE.allow(_encryptedValue, msg.sender); // User can decrypt hasValue = true; } // Make it public — anyone can decrypt function makePublic() external { require(hasValue, "No value set"); FHE.makePubliclyDecryptable(_encryptedValue); isPubliclyDecryptable = true; } // Return handle for off-chain decryption function getEncryptedValue() external view returns (euint32) { return _encryptedValue; }}
Flow:
User calls setValue(42) → value is encrypted, only they can decrypt
User calls makePublic() → now ANYONE can decrypt the value
Any user calls getEncryptedValue() → gets the handle → decrypts off-chain
it("should make value publicly decryptable", async function () { await contract.setValue(42); await contract.makePublic(); // After makePubliclyDecryptable, the value can be decrypted const handle = await contract.getEncryptedValue(); const value = await fhevm.userDecryptEuint( FhevmType.euint32, handle, contractAddress, deployer ); expect(value).to.equal(42n);});
Every decryption reveals information. Minimize decryptions to preserve privacy:
// ❌ BAD: Making value public just to comparefunction isRichBad() public { FHE.makePubliclyDecryptable(_balance); // Reveals exact balance!}// ✅ GOOD: Keep the comparison encryptedfunction isRich() public view returns (ebool) { return FHE.gt(_balance, FHE.asEuint64(1000)); // No value revealed}