Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions contracts/mocks/token/ERC7984FreezableMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@ contract ERC7984FreezableMock is ERC7984Mock, ERC7984Freezable, AccessControl, H
return super._update(from, to, amount);
}

function createEncryptedAmount(uint64 amount) public returns (euint64 encryptedAmount) {
FHE.allowThis(encryptedAmount = FHE.asEuint64(amount));
FHE.allow(encryptedAmount, msg.sender);
// solhint-disable-next-line func-name-mixedcase
function $_setConfidentialFrozen(
address account,
externalEuint64 encryptedAmount,
bytes calldata inputProof
) public virtual {
_setConfidentialFrozen(account, FHE.fromExternal(encryptedAmount, inputProof));
}

function confidentialAvailableAccess(address account) public {
Expand Down
18 changes: 0 additions & 18 deletions contracts/token/ERC7984/extensions/ERC7984Freezable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,6 @@ abstract contract ERC7984Freezable is ERC7984 {
return FHE.select(success, unfrozen, FHE.asEuint64(0));
}

/// @dev Freezes a confidential amount of tokens for an account with a proof.
function setConfidentialFrozen(
address account,
externalEuint64 encryptedAmount,
bytes calldata inputProof
) public virtual {
_setConfidentialFrozen(account, FHE.fromExternal(encryptedAmount, inputProof));
}

/// @dev Freezes a confidential amount of tokens for an account.
function setConfidentialFrozen(address account, euint64 encryptedAmount) public virtual {
require(
FHE.isAllowed(encryptedAmount, msg.sender),
ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
);
_setConfidentialFrozen(account, encryptedAmount);
}

/// @dev Internal function to freeze a confidential amount of tokens for an account.
function _setConfidentialFrozen(address account, euint64 encryptedAmount) internal virtual {
_checkFreezer();
Expand Down
124 changes: 51 additions & 73 deletions test/token/ERC7984/extensions/ERC7984Freezable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,63 +22,54 @@ describe('ERC7984Freezable', function () {
const acl = IACL__factory.connect(ACL_ADDRESS, ethers.provider);
return { token, acl, holder, recipient, freezer, operator, anyone };
}
for (const withProof of [true, false]) {
it(`should set and get confidential frozen ${withProof ? 'with proof' : ''}`, async function () {
const { token, acl, holder, recipient, freezer } = await deployFixture();
const encryptedRecipientMintInput = await fhevm
.createEncryptedInput(await token.getAddress(), holder.address)
.add64(1000)
.encrypt();
await token
.connect(holder)
['$_mint(address,bytes32,bytes)'](
recipient.address,
encryptedRecipientMintInput.handles[0],
encryptedRecipientMintInput.inputProof,
);
const amount = 100;
let params = [recipient.address] as unknown as [
account: AddressLike,
encryptedAmount: BytesLike,
inputProof: BytesLike,
];
if (withProof) {
const { handles, inputProof } = await fhevm
.createEncryptedInput(await token.getAddress(), freezer.address)
.add64(amount)
.encrypt();
params.push(handles[0], inputProof);
} else {
await token.connect(freezer).createEncryptedAmount(amount);
params.push(await token.connect(freezer).createEncryptedAmount.staticCall(amount));
}
await expect(
token
.connect(freezer)
[withProof ? 'setConfidentialFrozen(address,bytes32,bytes)' : 'setConfidentialFrozen(address,bytes32)'](
...params,
),
)
.to.emit(token, 'TokensFrozen')
.withArgs(recipient.address, params[1]);
const frozenHandle = await token.confidentialFrozen(recipient.address);
expect(frozenHandle).to.equal(ethers.hexlify(params[1]));
await expect(acl.isAllowed(frozenHandle, recipient.address)).to.eventually.be.true;
await expect(
fhevm.userDecryptEuint(FhevmType.euint64, frozenHandle, await token.getAddress(), recipient),
).to.eventually.equal(100);
const balanceHandle = await token.confidentialBalanceOf(recipient.address);
await expect(
fhevm.userDecryptEuint(FhevmType.euint64, balanceHandle, await token.getAddress(), recipient),
).to.eventually.equal(1000);
const confidentialAvailableArgs = recipient.address;
const availableHandle = await token.confidentialAvailable.staticCall(confidentialAvailableArgs);
await (token as any).connect(recipient).confidentialAvailableAccess(confidentialAvailableArgs);
await expect(
fhevm.userDecryptEuint(FhevmType.euint64, availableHandle, await token.getAddress(), recipient),
).to.eventually.equal(900);
});
}

it(`should set and get confidential frozen`, async function () {
const { token, acl, holder, recipient, freezer } = await deployFixture();
const encryptedRecipientMintInput = await fhevm
.createEncryptedInput(await token.getAddress(), holder.address)
.add64(1000)
.encrypt();
await token
.connect(holder)
['$_mint(address,bytes32,bytes)'](
recipient.address,
encryptedRecipientMintInput.handles[0],
encryptedRecipientMintInput.inputProof,
);

const amount = 100;
const { handles, inputProof } = await fhevm
.createEncryptedInput(await token.getAddress(), freezer.address)
.add64(amount)
.encrypt();

let params = [recipient.address, handles[0], inputProof] as unknown as [
account: AddressLike,
encryptedAmount: BytesLike,
inputProof: BytesLike,
];

await expect(token.connect(freezer)['$_setConfidentialFrozen(address,bytes32,bytes)'](...params))
.to.emit(token, 'TokensFrozen')
.withArgs(recipient.address, params[1]);

const frozenHandle = await token.confidentialFrozen(recipient.address);
expect(frozenHandle).to.equal(ethers.hexlify(params[1]));
await expect(acl.isAllowed(frozenHandle, recipient.address)).to.eventually.be.true;
await expect(
fhevm.userDecryptEuint(FhevmType.euint64, frozenHandle, await token.getAddress(), recipient),
).to.eventually.equal(100);
const balanceHandle = await token.confidentialBalanceOf(recipient.address);
await expect(
fhevm.userDecryptEuint(FhevmType.euint64, balanceHandle, await token.getAddress(), recipient),
).to.eventually.equal(1000);
const confidentialAvailableArgs = recipient.address;
const availableHandle = await token.confidentialAvailable.staticCall(confidentialAvailableArgs);
await (token as any).connect(recipient).confidentialAvailableAccess(confidentialAvailableArgs);
await expect(
fhevm.userDecryptEuint(FhevmType.euint64, availableHandle, await token.getAddress(), recipient),
).to.eventually.equal(900);
});

it('should not set confidential frozen if not called by freezer', async function () {
const { token, holder, recipient, anyone } = await deployFixture();
Expand All @@ -101,7 +92,7 @@ describe('ERC7984Freezable', function () {
await expect(
token
.connect(anyone)
['setConfidentialFrozen(address,bytes32,bytes)'](
['$_setConfidentialFrozen(address,bytes32,bytes)'](
recipient.address,
encryptedInput.handles[0],
encryptedInput.inputProof,
Expand Down Expand Up @@ -130,7 +121,7 @@ describe('ERC7984Freezable', function () {
.encrypt();
await token
.connect(freezer)
['setConfidentialFrozen(address,bytes32,bytes)'](
['$_setConfidentialFrozen(address,bytes32,bytes)'](
recipient.address,
encryptedInput.handles[0],
encryptedInput.inputProof,
Expand Down Expand Up @@ -181,7 +172,7 @@ describe('ERC7984Freezable', function () {
.encrypt();
await token
.connect(freezer)
['setConfidentialFrozen(address,bytes32,bytes)'](
['$_setConfidentialFrozen(address,bytes32,bytes)'](
recipient.address,
encryptedInput.handles[0],
encryptedInput.inputProof,
Expand Down Expand Up @@ -216,17 +207,4 @@ describe('ERC7984Freezable', function () {
),
).to.eventually.equal(1000);
});

it('should not set confidential frozen if unauthorized', async function () {
const { token, recipient, freezer, anyone } = await deployFixture();
const encryptedInput = await fhevm
.createEncryptedInput(await token.getAddress(), freezer.address)
.add64(100)
.encrypt();
await expect(
token.connect(anyone)['setConfidentialFrozen(address,bytes32)'](recipient.address, encryptedInput.handles[0]),
)
.to.be.revertedWithCustomError(token, 'ERC7984UnauthorizedUseOfEncryptedAmount')
.withArgs(encryptedInput.handles[0], anyone);
});
});
Loading