Skip to content

Commit 8d91ebe

Browse files
authored
Add internal function to wrapper that allows setting the max decimals (#89)
* Create an internal function to allow overriding the max decimals ConfidentialFungibleTokenERC20Wrapper * fix tets * Add changeset
1 parent 223da42 commit 8d91ebe

File tree

3 files changed

+57
-26
lines changed

3 files changed

+57
-26
lines changed

.changeset/six-walls-hug.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'openzeppelin-confidential-contracts': minor
3+
---
4+
5+
`ConfidentialFungibleTokenERC20Wrapper`: Add an internal function to allow overriding the maximum decimals value.

contracts/token/extensions/ConfidentialFungibleTokenERC20Wrapper.sol

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ abstract contract ConfidentialFungibleTokenERC20Wrapper is ConfidentialFungibleT
2727
_underlying = underlying_;
2828

2929
uint8 tokenDecimals = _tryGetAssetDecimals(underlying_);
30-
if (tokenDecimals > 9) {
31-
_decimals = 9;
32-
_rate = 10 ** (tokenDecimals - 9);
30+
uint8 maxDecimals = _maxDecimals();
31+
if (tokenDecimals > maxDecimals) {
32+
_decimals = maxDecimals;
33+
_rate = 10 ** (tokenDecimals - maxDecimals);
3334
} else {
3435
_decimals = tokenDecimals;
3536
_rate = 1;
@@ -154,6 +155,13 @@ abstract contract ConfidentialFungibleTokenERC20Wrapper is ConfidentialFungibleT
154155
_receivers[requestID] = to;
155156
}
156157

158+
/**
159+
* @dev Returns the maximum number that will be used for {decimals} by the wrapper.
160+
*/
161+
function _maxDecimals() internal pure virtual returns (uint8) {
162+
return 6;
163+
}
164+
157165
function _tryGetAssetDecimals(IERC20 asset_) private view returns (uint8 assetDecimals) {
158166
(bool success, bytes memory encodedDecimals) = address(asset_).staticcall(
159167
abi.encodeCall(IERC20Metadata.decimals, ())

test/token/extensions/ConfidentialFungibleWrapper.test.ts

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,27 @@ describe('ConfidentialFungibleTokenWrapper', function () {
4747
const wrappedBalanceHandle = await this.wrapper.confidentialBalanceOf(this.holder.address);
4848
await expect(
4949
fhevm.userDecryptEuint(FhevmType.euint64, wrappedBalanceHandle, this.wrapper.target, this.holder),
50-
).to.eventually.equal(ethers.parseUnits('100', 9));
50+
).to.eventually.equal(ethers.parseUnits('100', 6));
51+
});
52+
53+
it('with value less than rate', async function () {
54+
const amountToWrap = ethers.parseUnits('100', 8);
55+
56+
if (viaCallback) {
57+
await this.token.connect(this.holder).transferAndCall(this.wrapper, amountToWrap);
58+
} else {
59+
await this.wrapper.connect(this.holder).wrap(this.holder.address, amountToWrap);
60+
}
61+
62+
await expect(this.token.balanceOf(this.holder)).to.eventually.equal(ethers.parseUnits('1000', 18));
63+
const wrappedBalanceHandle = await this.wrapper.balanceOf(this.holder.address);
64+
await expect(
65+
fhevm.userDecryptEuint(FhevmType.euint64, wrappedBalanceHandle, this.wrapper.target, this.holder),
66+
).to.eventually.equal(0);
5167
});
5268

5369
it('with non-multiple of rate', async function () {
54-
const amountToWrap = ethers.parseUnits('101', 8);
70+
const amountToWrap = ethers.parseUnits('101', 11);
5571

5672
if (viaCallback) {
5773
await this.token.connect(this.holder).transferAndCall(this.wrapper, amountToWrap);
@@ -60,7 +76,7 @@ describe('ConfidentialFungibleTokenWrapper', function () {
6076
}
6177

6278
await expect(this.token.balanceOf(this.holder)).to.eventually.equal(
63-
ethers.parseUnits('1000', 18) - ethers.parseUnits('10', 9),
79+
ethers.parseUnits('1000', 18) - ethers.parseUnits('10', 12),
6480
);
6581
const wrappedBalanceHandle = await this.wrapper.confidentialBalanceOf(this.holder.address);
6682
await expect(
@@ -84,7 +100,7 @@ describe('ConfidentialFungibleTokenWrapper', function () {
84100
const wrappedBalanceHandle = await this.wrapper.confidentialBalanceOf(this.recipient.address);
85101
await expect(
86102
fhevm.userDecryptEuint(FhevmType.euint64, wrappedBalanceHandle, this.wrapper.target, this.recipient),
87-
).to.eventually.equal(ethers.parseUnits('100', 9));
103+
).to.eventually.equal(ethers.parseUnits('100', 6));
88104
});
89105

90106
it('from unauthorized caller', async function () {
@@ -104,10 +120,11 @@ describe('ConfidentialFungibleTokenWrapper', function () {
104120
});
105121

106122
it('less than balance', async function () {
107-
const withdrawalAmount = ethers.parseUnits('10', 9);
108-
const input = fhevm.createEncryptedInput(this.wrapper.target, this.holder.address);
109-
input.add64(withdrawalAmount);
110-
const encryptedInput = await input.encrypt();
123+
const withdrawalAmount = ethers.parseUnits('10', 6);
124+
const encryptedInput = await fhevm
125+
.createEncryptedInput(this.wrapper.target, this.holder.address)
126+
.add64(withdrawalAmount)
127+
.encrypt();
111128

112129
await this.wrapper
113130
.connect(this.holder)
@@ -122,7 +139,7 @@ describe('ConfidentialFungibleTokenWrapper', function () {
122139
await fhevm.awaitDecryptionOracle();
123140

124141
await expect(this.token.balanceOf(this.holder)).to.eventually.equal(
125-
withdrawalAmount * 10n ** 9n + ethers.parseUnits('900', 18),
142+
withdrawalAmount * 10n ** 12n + ethers.parseUnits('900', 18),
126143
);
127144
});
128145

@@ -175,10 +192,11 @@ describe('ConfidentialFungibleTokenWrapper', function () {
175192
});
176193

177194
it('via an approved operator', async function () {
178-
const withdrawalAmount = ethers.parseUnits('100', 9);
179-
const input = fhevm.createEncryptedInput(this.wrapper.target, this.operator.address);
180-
input.add64(withdrawalAmount);
181-
const encryptedInput = await input.encrypt();
195+
const withdrawalAmount = ethers.parseUnits('100', 6);
196+
const encryptedInput = await fhevm
197+
.createEncryptedInput(this.wrapper.target, this.operator.address)
198+
.add64(withdrawalAmount)
199+
.encrypt();
182200

183201
await this.wrapper.connect(this.holder).setOperator(this.operator.address, Math.round(Date.now() / 1000) + 1000);
184202

@@ -232,16 +250,16 @@ describe('ConfidentialFungibleTokenWrapper', function () {
232250

233251
describe('Initialization', function () {
234252
describe('decimals', function () {
235-
it('when underlying has 9 decimals', async function () {
236-
const token = await ethers.deployContract('ERC20Mock', ['Public Token', 'PT', 9]);
253+
it('when underlying has 6 decimals', async function () {
254+
const token = await ethers.deployContract('ERC20Mock', ['Public Token', 'PT', 6]);
237255
const wrapper = await ethers.deployContract('ConfidentialFungibleTokenERC20WrapperMock', [
238256
token,
239257
name,
240258
symbol,
241259
uri,
242260
]);
243261

244-
await expect(wrapper.decimals()).to.eventually.equal(9);
262+
await expect(wrapper.decimals()).to.eventually.equal(6);
245263
await expect(wrapper.rate()).to.eventually.equal(1);
246264
});
247265

@@ -254,20 +272,20 @@ describe('ConfidentialFungibleTokenWrapper', function () {
254272
uri,
255273
]);
256274

257-
await expect(wrapper.decimals()).to.eventually.equal(9);
258-
await expect(wrapper.rate()).to.eventually.equal(10n ** 9n);
275+
await expect(wrapper.decimals()).to.eventually.equal(6);
276+
await expect(wrapper.rate()).to.eventually.equal(10n ** 12n);
259277
});
260278

261-
it('when underlying has less than 9 decimals', async function () {
262-
const token = await ethers.deployContract('ERC20Mock', ['Public Token', 'PT', 8]);
279+
it('when underlying has less than 6 decimals', async function () {
280+
const token = await ethers.deployContract('ERC20Mock', ['Public Token', 'PT', 4]);
263281
const wrapper = await ethers.deployContract('ConfidentialFungibleTokenERC20WrapperMock', [
264282
token,
265283
name,
266284
symbol,
267285
uri,
268286
]);
269287

270-
await expect(wrapper.decimals()).to.eventually.equal(8);
288+
await expect(wrapper.decimals()).to.eventually.equal(4);
271289
await expect(wrapper.rate()).to.eventually.equal(1);
272290
});
273291

@@ -280,8 +298,8 @@ describe('ConfidentialFungibleTokenWrapper', function () {
280298
uri,
281299
]);
282300

283-
await expect(wrapper.decimals()).to.eventually.equal(9);
284-
await expect(wrapper.rate()).to.eventually.equal(10n ** 9n);
301+
await expect(wrapper.decimals()).to.eventually.equal(6);
302+
await expect(wrapper.rate()).to.eventually.equal(10n ** 12n);
285303
});
286304

287305
it('when decimals are over `type(uint8).max`', async function () {

0 commit comments

Comments
 (0)