Skip to content

Commit 3bb9955

Browse files
authored
docs(protocol-contracts): improve wrapper documentation on decimals (#1661)
1 parent ebd0fe6 commit 3bb9955

File tree

1 file changed

+41
-14
lines changed
  • protocol-contracts/confidential-wrapper/docs

1 file changed

+41
-14
lines changed

protocol-contracts/confidential-wrapper/docs/README.md

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ The **Confidential Wrapper** is a smart contract that wraps standard ERC-20 toke
1212
- **Operator**: An address authorized to transfer confidential tokens on behalf of another address.
1313
- **Owner**: The owner of the wrapper contract. In the FHEVM protocol, this is initially set to a DAO governance contract handled by Zama. Ownership will then be transferred to the underlying token's owner.
1414
- **Registry**: The registry contract that maps ERC-20 tokens to their corresponding confidential wrappers. More information [here](../../confidential-token-wrappers-registry/docs/README.md).
15-
- **ACL**: The ACL contract that manages the ACL permissions for encrypted amounts. More information in the [FHEVM library documentation](https://docs.zama.org/protocol/protocol/overview/library#access-control).
15+
- **ACL**: The Access Control List (ACL) contract that manages the permissions for encrypted amounts. More information in the [FHEVM library documentation](https://docs.zama.org/protocol/protocol/overview/library#access-control).
1616
- **Input proof**: A proof that the encrypted amount is valid. More information in the [`relayer-sdk` documentation](https://docs.zama.org/protocol/relayer-sdk-guides/fhevm-relayer/input).
1717
- **Public decryption**: A request to publicly decrypt an encrypted amount. More information in the [`relayer-sdk` documentation](https://docs.zama.org/protocol/relayer-sdk-guides/fhevm-relayer/decryption/public-decryption).
1818

1919
## Quick Start
2020

21-
> ⚠️ **Decimal conversion:** The wrapper enforces a maximum of **6 decimals** for the confidential token. When wrapping, amounts are rounded down and excess tokens are refunded.
21+
> ⚠️ **Decimal conversion:** The wrapper enforces a maximum number of decimals for the confidential token. When wrapping, amounts are rounded down and excess tokens are refunded. Currently, this maximum is set to **6 decimals** only. See [Maximum number of decimals](#maximum-number-of-decimals) for more information.
2222
2323
> ⚠️ **Unsupported tokens:** Non-standard tokens such as fee-on-transfer or any deflationary-type tokens are NOT supported.
2424
@@ -102,17 +102,17 @@ This finalizes the unwrap request by sending the corresponding amount of underly
102102
#### Direct transfer
103103

104104
```solidity
105-
token.confidentialTransfer(to, encryptedAmount, inputProof);
105+
wrapper.confidentialTransfer(to, encryptedAmount, inputProof);
106106
107-
token.confidentialTransfer(to, encryptedAmount);
107+
wrapper.confidentialTransfer(to, encryptedAmount);
108108
```
109109

110110
#### Operator-based transfer
111111

112112
```solidity
113-
token.confidentialTransferFrom(from, to, encryptedAmount, inputProof);
113+
wrapper.confidentialTransferFrom(from, to, encryptedAmount, inputProof);
114114
115-
token.confidentialTransferFrom(from, to, encryptedAmount);
115+
wrapper.confidentialTransferFrom(from, to, encryptedAmount);
116116
```
117117

118118
Considerations:
@@ -123,19 +123,19 @@ Considerations:
123123
The callback can be used along an ERC-7984 receiver contract.
124124

125125
```solidity
126-
token.confidentialTransferAndCall(to, encryptedAmount, inputProof, callbackData);
126+
wrapper.confidentialTransferAndCall(to, encryptedAmount, inputProof, callbackData);
127127
128-
token.confidentialTransferAndCall(to, encryptedAmount, callbackData);
128+
wrapper.confidentialTransferAndCall(to, encryptedAmount, callbackData);
129129
```
130130

131131
#### Operator-based transfer with callback
132132

133133
The callback can be used along an ERC-7984 receiver contract.
134134

135135
```solidity
136-
token.confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, callbackData);
136+
wrapper.confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, callbackData);
137137
138-
token.confidentialTransferFromAndCall(from, to, encryptedAmount, callbackData);
138+
wrapper.confidentialTransferFromAndCall(from, to, encryptedAmount, callbackData);
139139
```
140140

141141
Considerations:
@@ -193,10 +193,10 @@ Delegate transfer capabilities with time-based expiration:
193193

194194
```solidity
195195
// Grant operator permission until a specific timestamp
196-
token.setOperator(operatorAddress, validUntilTimestamp);
196+
wrapper.setOperator(operatorAddress, validUntilTimestamp);
197197
198198
// Check if an address is an authorized operator
199-
bool isAuthorized = token.isOperator(holder, spender);
199+
bool isAuthorized = wrapper.isOperator(holder, spender);
200200
```
201201

202202
### Amount disclosure
@@ -205,10 +205,10 @@ Optionally reveal encrypted amounts publicly:
205205

206206
```solidity
207207
// Request disclosure (initiates async decryption)
208-
token.requestDiscloseEncryptedAmount(encryptedAmount);
208+
wrapper.requestDiscloseEncryptedAmount(encryptedAmount);
209209
210210
// Complete disclosure with proof
211-
token.discloseEncryptedAmount(encryptedAmount, cleartextAmount, decryptionProof);
211+
wrapper.discloseEncryptedAmount(encryptedAmount, cleartextAmount, decryptionProof);
212212
```
213213

214214
### Check ACL permissions
@@ -277,6 +277,33 @@ Transfer functions with `euint64` (not `externalEuint64`) require the caller to
277277

278278
The unwrap mechanism stores requests in a mapping keyed by ciphertext and the current implementation assumes these ciphertexts are unique. This holds in this very specific case but be aware of this architectural decision as it is **NOT** true in the general case.
279279

280+
### Maximum number of decimals
281+
282+
The maximum number of decimals `_maxDecimals()` for the confidential token is currently set to **6 decimals** only. This is due to FHE limitations as confidential balances must be represented by the euint64 encrypted datatype.
283+
284+
It is possible that future implementations of the wrapper set a higher `_maxDecimals()` value to better suit the needs of the underlying token. For example, cWBTC might require 8 decimals since using only 6 would make the smallest unit impractically expensive.
285+
286+
At deployment, the confidential wrapper sets its number of decimals as:
287+
- the number of decimals of the underlying token if it is less than `_maxDecimals()`
288+
- `_maxDecimals()` otherwise
289+
290+
**Example with `_maxDecimals()` set to 6**
291+
| Underlying Decimals | Wrapper Decimals | Example |
292+
|---------------------|------------------|---------|
293+
| 18 | 6 | ZAMA/cZAMA
294+
| 6 | 6 | USDT/cUSDT
295+
| 2 | 2 | GUSD/cGUSD
296+
297+
Once a confidential wrapper contract is deployed, this number cannot be updated. It can be viewed with the following view function:
298+
299+
```solidity
300+
wrapper.decimals();
301+
```
302+
303+
### Maximum total supply
304+
305+
The maximum total supply for the confidential token is currently set to `type(uint64).max` (`2^64 - 1`) due to FHE limitations.
306+
280307
---
281308

282309
## Interface Support (ERC-165)

0 commit comments

Comments
 (0)