To close this concepts guide, here are some best practices to keep in mind when creating your confidential dapps.

Always check allowance over inputs

As we have seen in the confidential token example, most of your external facing functions that expose a confidential input will want to be declared twice like so.

function transfer(address to, bytes memory valueInput) external returns (ebool) {
    euint256 value = valueInput.newEuint256(msg.sender);
    return _transfer(to, value);
}

function transfer(address to, euint256 value) public returns (ebool success) {
    require(msg.sender.isAllowed(value), "SimpleConfidentialToken: unauthorized value handle access");
    return _transfer(to, value);
}

This is because one function is meant to receive a ciphertext created offchain, and the other is meant to be called by smart contracts sending an existing e-variable. In the second function, you should always check that the caller has access to the ciphertext handle that is passed as an argument. This is done by performing a require over msg.sender.isAllowed(value). This is important because the caller may use an existing handle that it has not access to but that the contract has access to. In this case, depending on the contract, the caller may be to deduce or gain access to the value in used as input.

Think in terms of information leakage

When designing an app, you need to be mindful not only to who receives access over the ciphertexts, but also about what can be deduced from the information that is publicly available.

For example, if we were to naively port Uniswap pools to Inco, we may want to accept confidential input amounts for a swap and send confidential output amounts. If the price of the pool is public, then the swapped amount can be deduced by comparing the price before and after the swap.

In another example, if you are holding a secret auction where the current highest bidder is continuously updated, one can deduce the current highest bid by submitting increasingly large bids until it becomes the highest bidder.

This kind of possible deductions are called information leakage, and may show up often in your dapps.

Don’t lose access over your ciphertexts

Don’t forget to call e.allowThis() and e.allow after an operation. By default, after the transaction is included, no one retains access to the new handles being created and the contract will not be able to compute over them in the future, and the user won’t be able to see them if not granted access.

Be extra careful of delegatecalls

A contract being delegatecalled can decrypt any ciphertext your contract holds or share access to it.

Don’t hesitate to contact us for any question or if you want to discuss your dapp design. We are also interested in your feedback on this doc.