Branching in FHE
The result of comparison operations is of type ebool
. Typical boolean operations are not supported for this type, because it is an encrypted boolean.
Condition with encrypted boolean
fhEVM provides a method which acts as a ternary operator on encrypted integers. This method is called select.
function bid(bytes calldata encryptedBid) internal {
euint32 bid = TFHE.asEuint32(encryptedBid);
ebool isAbove = TFHE.le(bid, highestBid);
// Replace highest bid
highestBid = TFHE.select(isAbove, bid, highestBid);
}
It is important to keep in mind that each time we assign a value using TFHE.select
, the value changes, even if the plaintext value remains the same.
Error handling
If a condition is not satisfied, the transaction will not be reverted, potentially posing a challenge when attempting to communicate issues to users. A recommended approach to address this is by implementing an error handler in which the contract stores the latest error information for all wallets.
struct LastError {
euint8 error;
uint timestamp;
}
euint8 internal NO_ERROR;
euint8 internal NOT_ENOUGH_FUND;
constructor() {
NO_ERROR = TFHE.asEuint8(0);
NOT_ENOUGH_FUND = TFHE.asEuint8(1);
}
function setLastError(euint8 error, address addr) private {
_lastErrors[addr] = LastError(error, block.timestamp);
emit ErrorChanged(addr);
}
function _transfer(address from, address to, euint32 amount) internal {
// Make sure the sender has enough tokens.
ebool canTransfer = TFHE.le(amount, balances[from]);
setLastError(TFHE.select(canTransfer, NO_ERROR, NOT_ENOUGH_FUND), msg.sender);
// Add to the balance of `to` and subract from the balance of `from`.
balances[to] = balances[to] + TFHE.select(canTransfer, amount, TFHE.asEuint32(0));
balances[from] = balances[from] - TFHE.select(canTransfer, amount, TFHE.asEuint32(0));
}
Last updated
Was this helpful?