The access control logic is fully programmable and onchain. Who has the right to decrypt and see a give ciphertext is visible onchain.

To give access to an account (i.e an address) to a ciphertext, you can use the e.allow function. This will grant the address permanent access to seeing, publicly decrypting and computing over the ciphertext.

Since handles are immutable, sharing access to a variable to an account only grants access to the current value of the variable. Whenever the variable is updated, the handle changes and the access to the new handle must be granted again. For example, ou can share your current balance with an address, but if you update your balance, the address will not be able to see the new value.

Example usage from the confidential token contract:

function _transfer(address to, euint256 value) internal returns (ebool success) {
    // ... some previous logic
    // allow the sender to see its new balance
    senderNewBalance.allow(msg.sender);
    // allow the receiver to see its new balance
    receiverNewBalance.allow(to);
    // allow this contract to be able to compute over the new balances in future transfers
    senderNewBalance.allowThis();
    receiverNewBalance.allowThis();
    // let the caller know if the transfer was successful
    success.allow(msg.sender);
}

e.allowThis(value) is an alias for e.allow(value, address(this)).

A common mistake is to forget to call allowThis on a variable after updating it. This will result in the contract being unable to compute over the variable in future transactions.

Always call e.allowThis after updating a variable, if this variable will be used in your contract again.

Transient Allowance

e.transientAllow is not yet available in the SDK, but coming very soon.

A transient allowance is an allowance that is valid only for the current transaction. All results of operations such as e.add are transiently allowed to be decrypted by the contract who called the operation. That is why contracts can perform back to back operations using results of previous operations. But since this allowance is transient, calling e.allowThis is necessary to allow the contract to compute over the result in future transactions.

How to reason about access

The correct way to think of access control is to consider that each account (i.e any address of EOA/contract/smart wallet) that received access to a ciphertext at some point, either transiently or permanently, knows its value, has stored it, and may compute over it. Note that once the access over a ciphertext is shared, the receiving account may share it with any other account, or publicly decrypt it. Be very mindful of the access you grant over your ciphertexts in your apps, and don’t consider transient allowances to be “safer” in any way than permanent ones.