AntiPatternMissingAllowThis

Category: Basic | Difficulty: Intermediate | Chapters: Anti Patterns | Concept: Missing FHE.allowThis breaks reuse of stored handles

Demonstrates the pitfall of omitting FHE.allowThis on stored values.

Why this example

This example focuses on Missing FHE.allowThis breaks reuse of stored handles. It is designed to be self-contained and easy to run locally.

Quick start

npm install
npm run test:mocked -- test/basic/AntiPatternMissingAllowThis.test.ts

Dependencies

None

Contract and test

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import {FHE, euint64, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
import {ZamaEthereumConfig} from "@fhevm/solidity/config/ZamaConfig.sol";

/**
 * @title AntiPatternMissingAllowThis
 * @author Gustavo Valverde
 * @notice Demonstrates the pitfall of omitting FHE.allowThis on stored values.
 * @dev Example for fhEVM Examples - Basic Category
 *
 * @custom:category basic
 * @custom:chapter anti-patterns
 * @custom:concept Missing FHE.allowThis breaks reuse of stored handles
 * @custom:difficulty intermediate
 */
contract AntiPatternMissingAllowThis is ZamaEthereumConfig {
    mapping(address user => euint64 value) private storedValues;

    /// @notice Store an encrypted value without granting the contract permission.
    /// @param encValue Encrypted value handle
    /// @param inputProof Proof for the encrypted input
    function storeValue(externalEuint64 encValue, bytes calldata inputProof) external {
        euint64 value = FHE.fromExternal(encValue, inputProof);
        storedValues[msg.sender] = value;
        // Intentionally missing FHE.allowThis(value)
        FHE.allow(value, msg.sender);
    }

    /// @notice Try to reuse the stored value (expected to fail in practice).
    /// @param encValue Encrypted value handle
    /// @param inputProof Proof for the encrypted input
    function addToStored(externalEuint64 encValue, bytes calldata inputProof) external {
        euint64 value = FHE.fromExternal(encValue, inputProof);
        euint64 updated = FHE.add(storedValues[msg.sender], value);
        storedValues[msg.sender] = updated;
        FHE.allowThis(updated);
        FHE.allow(updated, msg.sender);
    }

    /// @notice Retrieve the stored value.
    /// @param user Account holding the encrypted value
    /// @return The stored encrypted value
    function getStoredValue(address user) external view returns (euint64) {
        return storedValues[user];
    }
}

Pitfalls to avoid

  • should fail when reusing a handle without allowThis

API Reference

Overview

Demonstrates the pitfall of omitting FHE.allowThis on stored values.

Developer Notes

Example for fhEVM Examples - Basic Category

storeValue

Store an encrypted value without granting the contract permission.

Parameters

Name
Type
Description

encValue

externalEuint64

Encrypted value handle

inputProof

bytes

Proof for the encrypted input

addToStored

Try to reuse the stored value (expected to fail in practice).

Parameters

Name
Type
Description

encValue

externalEuint64

Encrypted value handle

inputProof

bytes

Proof for the encrypted input

getStoredValue

Retrieve the stored value.

Parameters

Name
Type
Description

user

address

Account holding the encrypted value

Return Values

Name
Type
Description

[0]

euint64

The stored encrypted value

Last updated