Context: contracts/experimental/token/FHERC20/FHERC20.sol
Severity: INFO
Description
The contract exposes underscore-prefixed functions _transferEncrypted and _transferFromEncrypted as public and they accept euint128 directly. Unlike the inEuint128-based entrypoints (transferEncrypted/transferFromEncrypted), passing euint128 bypasses FHE.asEuint128(inEuint128) verification of user-supplied ciphertext bytes (which is intended to validate ciphertext correctness and security zone).
If the underlying FHE runtime does not strictly bind ciphertext handles to the calling contract and validate them on every operation, an attacker could pass crafted/foreign ciphertext handles to influence comparisons (lte/gte) and arithmetic in unexpected ways (e.g., forcing transfers of unintended amounts or causing runtime reverts). Even if the runtime is robust, leaving these as public increases the attack surface and makes it easier to accidentally integrate the unsafe entrypoints.
If an attacker calls _transferFromEncrypted directly with a malformed euint128 handle, potentially triggering a precompile revert during FHE operations and breaking higher-level batching/multicall workflows that include FHERC20 interactions.
function _transferFromEncrypted(address from, address to, euint128 value) public virtual returns (euint128) {
euint128 val = value;
euint128 spent = _spendAllowance(from, msg.sender, val);
return _transferImpl(from, to, spent);
}
// Transfers an amount from the message sender address to the `to` address.
function _transferEncrypted(address to, euint128 amount) public returns (euint128) {
return _transferImpl(msg.sender, to, amount);
}
Recommendation
Make _transferEncrypted and _transferFromEncrypted internal (or private) and keep only the inEuint128-validated public entrypoints.
If external raw-ciphertext entrypoints are required, explicitly validate the ciphertext (e.g., by requiring inEuint128 input) and document supported security zones.
Impacted Code (L66-L111):
Context:
contracts/experimental/token/FHERC20/FHERC20.solSeverity: INFO
Description
The contract exposes underscore-prefixed functions
_transferEncryptedand_transferFromEncryptedaspublicand they accepteuint128directly. Unlike theinEuint128-based entrypoints (transferEncrypted/transferFromEncrypted), passingeuint128bypassesFHE.asEuint128(inEuint128)verification of user-supplied ciphertext bytes (which is intended to validate ciphertext correctness and security zone).If the underlying FHE runtime does not strictly bind ciphertext handles to the calling contract and validate them on every operation, an attacker could pass crafted/foreign ciphertext handles to influence comparisons (
lte/gte) and arithmetic in unexpected ways (e.g., forcing transfers of unintended amounts or causing runtime reverts). Even if the runtime is robust, leaving these as public increases the attack surface and makes it easier to accidentally integrate the unsafe entrypoints.If an attacker calls
_transferFromEncrypteddirectly with a malformedeuint128handle, potentially triggering a precompile revert during FHE operations and breaking higher-level batching/multicall workflows that include FHERC20 interactions.Recommendation
Make
_transferEncryptedand_transferFromEncryptedinternal(orprivate) and keep only theinEuint128-validated public entrypoints.If external raw-ciphertext entrypoints are required, explicitly validate the ciphertext (e.g., by requiring
inEuint128input) and document supported security zones.Impacted Code (L66-L111):