Skip to content
Draft
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
3 changes: 0 additions & 3 deletions contracts/interfaces/IERC7984.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ interface IERC7984 is IERC165 {
/// @dev Returns the number of decimals of the token. Recommended to be 6.
function decimals() external view returns (uint8);

/// @dev Returns the contract URI. See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572] for details.
function contractURI() external view returns (string memory);

/// @dev Returns the confidential total supply of the token.
function confidentialTotalSupply() external view returns (euint64);

Expand Down
11 changes: 11 additions & 0 deletions contracts/interfaces/IERC7984ContractURI.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;
Comment thread
arr00 marked this conversation as resolved.

import {IERC7984} from "./IERC7984.sol";

/// @dev Interface for the optional {contractURI} function for {IERC7984}.
interface IERC7984ContractURI is IERC7984 {
/// @dev Returns the contract URI. Should be formatted as described in https://eips.ethereum.org/EIPS/eip-7572[ERC-7572].
function contractURI() external view returns (string memory);
}
7 changes: 1 addition & 6 deletions contracts/mocks/docs/ERC7984MintableBurnable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC7984} from "../../token/ERC7984/ERC7984.sol";

contract ERC7984MintableBurnable is ERC7984, Ownable {
constructor(
address owner,
string memory name,
string memory symbol,
string memory uri
) ERC7984(name, symbol, uri) Ownable(owner) {}
constructor(address owner, string memory name, string memory symbol) ERC7984(name, symbol) Ownable(owner) {}

function mint(address to, externalEuint64 amount, bytes memory inputProof) public onlyOwner {
_mint(to, FHE.fromExternal(amount, inputProof));
Expand Down
29 changes: 29 additions & 0 deletions contracts/mocks/token/ERC7984ContractURIMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.27;

import {euint64} from "@fhevm/solidity/lib/FHE.sol";
import {ERC7984ContractURI} from "../../token/ERC7984/extensions/ERC7984ContractURI.sol";
import {ERC7984Mock, ERC7984} from "./ERC7984Mock.sol";

contract ERC7984ContractURIMock is ERC7984ContractURI, ERC7984Mock {
constructor(
string memory name_,
string memory symbol_,
string memory contractURI_
) ERC7984Mock(name_, symbol_) ERC7984ContractURI(contractURI_) {}

function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC7984ContractURI, ERC7984) returns (bool) {
return super.supportsInterface(interfaceId);
}

function _update(
address from,
address to,
euint64 amount
) internal virtual override(ERC7984Mock, ERC7984) returns (euint64) {
return super._update(from, to, amount);
}
}
5 changes: 2 additions & 3 deletions contracts/mocks/token/ERC7984ERC20WrapperMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ contract ERC7984ERC20WrapperMock is ERC7984ERC20Wrapper, ZamaEthereumConfig {
constructor(
IERC20 token,
string memory name,
string memory symbol,
string memory uri
) ERC7984ERC20Wrapper(token) ERC7984(name, symbol, uri) {}
string memory symbol
) ERC7984ERC20Wrapper(token) ERC7984(name, symbol) {}
}
2 changes: 1 addition & 1 deletion contracts/mocks/token/ERC7984FreezableMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {ERC7984Mock} from "./ERC7984Mock.sol";
contract ERC7984FreezableMock is ERC7984Mock, ERC7984Freezable, HandleAccessManager {
error UnallowedHandleAccess(bytes32 handle, address account);

constructor(string memory name, string memory symbol, string memory tokenUri) ERC7984Mock(name, symbol, tokenUri) {}
constructor(string memory name, string memory symbol) ERC7984Mock(name, symbol) {}

function _update(
address from,
Expand Down
6 changes: 1 addition & 5 deletions contracts/mocks/token/ERC7984Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ contract ERC7984Mock is ERC7984, ZamaEthereumConfig {
event EncryptedAmountCreated(euint64 amount);
event EncryptedAddressCreated(eaddress addr);

constructor(
string memory name_,
string memory symbol_,
string memory tokenURI_
) ERC7984(name_, symbol_, tokenURI_) {
constructor(string memory name_, string memory symbol_) ERC7984(name_, symbol_) {
_OWNER = msg.sender;
}

Expand Down
6 changes: 1 addition & 5 deletions contracts/mocks/token/ERC7984ObserverAccessMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import {ERC7984ObserverAccess} from "../../token/ERC7984/extensions/ERC7984Obser
import {ERC7984Mock} from "./ERC7984Mock.sol";

contract ERC7984ObserverAccessMock is ERC7984ObserverAccess, ERC7984Mock {
constructor(
string memory name_,
string memory symbol_,
string memory tokenURI_
) ERC7984Mock(name_, symbol_, tokenURI_) {}
constructor(string memory name_, string memory symbol_) ERC7984Mock(name_, symbol_) {}

function _update(
address from,
Expand Down
6 changes: 1 addition & 5 deletions contracts/mocks/token/ERC7984ReentrantMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ import {euint64} from "@fhevm/solidity/lib/FHE.sol";
import {ERC7984Mock} from "./ERC7984Mock.sol";

contract ERC7984ReentrantMock is ERC7984Mock {
constructor(
string memory name_,
string memory symbol_,
string memory tokenURI_
) ERC7984Mock(name_, symbol_, tokenURI_) {}
constructor(string memory name_, string memory symbol_) ERC7984Mock(name_, symbol_) {}

function confidentialTransfer(address, euint64) public override returns (euint64 transferred) {
IVestingWalletConfidential(msg.sender).release(address(this));
Expand Down
7 changes: 1 addition & 6 deletions contracts/mocks/token/ERC7984RwaMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@ import {ERC7984Mock} from "./ERC7984Mock.sol";

// solhint-disable func-name-mixedcase
contract ERC7984RwaMock is ERC7984Rwa, ERC7984Mock, HandleAccessManager {
constructor(
string memory name,
string memory symbol,
string memory tokenUri,
address admin
) ERC7984Rwa(admin) ERC7984Mock(name, symbol, tokenUri) {}
constructor(string memory name, string memory symbol, address admin) ERC7984Rwa(admin) ERC7984Mock(name, symbol) {}

function supportsInterface(bytes4 interfaceId) public view virtual override(ERC7984Rwa, ERC7984) returns (bool) {
return super.supportsInterface(interfaceId);
Expand Down
6 changes: 1 addition & 5 deletions contracts/mocks/token/ERC7984VotesMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ abstract contract ERC7984VotesMock is ERC7984Mock, ERC7984Votes {

uint48 private _clockOverrideVal;

constructor(
string memory name_,
string memory symbol_,
string memory tokenURI_
) ERC7984Mock(name_, symbol_, tokenURI_) EIP712(name_, "1.0.0") {
constructor(string memory name_, string memory symbol_) ERC7984Mock(name_, symbol_) EIP712(name_, "1.0.0") {
_OWNER = msg.sender;
}

Expand Down
9 changes: 1 addition & 8 deletions contracts/token/ERC7984/ERC7984.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ abstract contract ERC7984 is IERC7984, ERC165 {
euint64 private _totalSupply;
string private _name;
string private _symbol;
string private _contractURI;

/// @dev Emitted when an encrypted amount `encryptedAmount` is requested for disclosure by `requester`.
event AmountDiscloseRequested(euint64 indexed encryptedAmount, address indexed requester);
Expand Down Expand Up @@ -60,10 +59,9 @@ abstract contract ERC7984 is IERC7984, ERC165 {
/// @dev The given gateway request ID `requestId` is invalid.
error ERC7984InvalidGatewayRequest(uint256 requestId);

constructor(string memory name_, string memory symbol_, string memory contractURI_) {
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
_contractURI = contractURI_;
}

/// @inheritdoc ERC165
Expand All @@ -86,11 +84,6 @@ abstract contract ERC7984 is IERC7984, ERC165 {
return 6;
}

/// @inheritdoc IERC7984
function contractURI() public view virtual returns (string memory) {
return _contractURI;
}

/// @inheritdoc IERC7984
function confidentialTotalSupply() public view virtual returns (euint64) {
return _totalSupply;
Expand Down
42 changes: 42 additions & 0 deletions contracts/token/ERC7984/extensions/ERC7984ContractURI.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Confidential Contracts (token/ERC7984/extensions/ERC7984ContractURI.sol)
pragma solidity ^0.8.27;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {IERC7984ContractURI} from "../../../interfaces/IERC7984ContractURI.sol";
import {ERC7984} from "../ERC7984.sol";

/**
* @dev Extension of {ERC7984} that adds a {contractURI} function.
*/
abstract contract ERC7984ContractURI is IERC7984ContractURI, ERC7984 {
/// @dev Event emitted when the contract URI is changed.
event ContractURIUpdated();

string private _contractURI;

constructor(string memory contractURI_) {
_setContractURI(contractURI_);
}

/// @inheritdoc IERC7984ContractURI
function contractURI() public view virtual returns (string memory) {
return _contractURI;
}

/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC7984, IERC165) returns (bool) {
return interfaceId == type(IERC7984ContractURI).interfaceId || super.supportsInterface(interfaceId);
}

/**
* @dev Sets the {contractURI} for the contract.
*
* Emits a {ContractURIUpdated} event.
*/
function _setContractURI(string memory newContractURI) internal virtual {
_contractURI = newContractURI;

emit ContractURIUpdated();
}
}
2 changes: 2 additions & 0 deletions contracts/token/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This set of interfaces, contracts, and utilities are all related to `ERC7984`, a
- {ERC7984Rwa}: Extension of {ERC7984} that supports confidential Real World Assets (RWAs) by providing compliance checks, transfer controls and enforcement actions.
- {ERC7984Votes}: An extension of {ERC7984} that supports confidential vote tracking and delegation via {VotesConfidential}.
- {ERC7984Utils}: A library that provides the on-transfer callback check used by {ERC7984}.
- {ERC7984ContractURI}: An extension of {ERC7984} that adds the `contractURI()` function--allowing for additional metadata to be associated with the token.

== Core
{{ERC7984}}
Expand All @@ -26,6 +27,7 @@ This set of interfaces, contracts, and utilities are all related to `ERC7984`, a
{{ERC7984Omnibus}}
{{ERC7984Rwa}}
{{ERC7984Votes}}
{{ERC7984ContractURI}}

== Utilities
{{ERC7984Utils}}
3 changes: 1 addition & 2 deletions test/finance/ERC7821WithExecutor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ import { ethers, fhevm } from 'hardhat';

const name = 'ConfidentialFungibleToken';
const symbol = 'CFT';
const uri = 'https://example.com/metadata';

describe('ERC7821WithExecutor', function () {
beforeEach(async function () {
const [recipient, executor, ...accounts] = await ethers.getSigners();

const token = await ethers.deployContract('$ERC7984Mock', [name, symbol, uri]);
const token = await ethers.deployContract('$ERC7984Mock', [name, symbol]);

const encryptedInput = await fhevm
.createEncryptedInput(await token.getAddress(), recipient.address)
Expand Down
3 changes: 1 addition & 2 deletions test/finance/VestingWalletCliffConfidential.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import { ethers, fhevm } from 'hardhat';

const name = 'ConfidentialFungibleToken';
const symbol = 'CFT';
const uri = 'https://example.com/metadata';

describe(`VestingWalletCliffConfidential`, function () {
beforeEach(async function () {
const accounts = (await ethers.getSigners()).slice(3);
const [holder, recipient] = accounts;

const token = await ethers.deployContract('$ERC7984Mock', [name, symbol, uri]);
const token = await ethers.deployContract('$ERC7984Mock', [name, symbol]);

const encryptedInput = await fhevm
.createEncryptedInput(await token.getAddress(), holder.address)
Expand Down
2 changes: 1 addition & 1 deletion test/finance/VestingWalletConfidential.behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function shouldBehaveLikeVestingConfidential() {
});

it('should not release if reentrancy', async function () {
const reentrantToken = await ethers.deployContract('$ERC7984ReentrantMock', ['name', 'symbol', 'uri']);
const reentrantToken = await ethers.deployContract('$ERC7984ReentrantMock', ['name', 'symbol']);
const encryptedInput = await fhevm
.createEncryptedInput(await reentrantToken.getAddress(), this.holder.address)
.add64(1000)
Expand Down
3 changes: 1 addition & 2 deletions test/finance/VestingWalletConfidential.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import { ethers, fhevm } from 'hardhat';

const name = 'ConfidentialFungibleToken';
const symbol = 'CFT';
const uri = 'https://example.com/metadata';

describe('VestingWalletConfidential', function () {
beforeEach(async function () {
const accounts = (await ethers.getSigners()).slice(3);
const [holder, recipient] = accounts;

const token = await ethers.deployContract('$ERC7984Mock', [name, symbol, uri]);
const token = await ethers.deployContract('$ERC7984Mock', [name, symbol]);

const encryptedInput = await fhevm
.createEncryptedInput(await token.getAddress(), holder.address)
Expand Down
3 changes: 1 addition & 2 deletions test/finance/VestingWalletConfidentialFactory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { ethers, fhevm } from 'hardhat';

const name = 'ConfidentialFungibleToken';
const symbol = 'CFT';
const uri = 'https://example.com/metadata';
const startTimestamp = 9876543210;
const duration = 1234;
const cliff = 10;
Expand All @@ -20,7 +19,7 @@ describe('VestingWalletCliffExecutorConfidentialFactory', function () {
beforeEach(async function () {
const [holder, recipient, recipient2, operator, executor, ...accounts] = await ethers.getSigners();

const token = (await ethers.deployContract('$ERC7984Mock', [name, symbol, uri])) as any as $ERC7984Mock;
const token = (await ethers.deployContract('$ERC7984Mock', [name, symbol])) as any as $ERC7984Mock;

const encryptedInput = await fhevm
.createEncryptedInput(await token.getAddress(), holder.address)
Expand Down
2 changes: 1 addition & 1 deletion test/helpers/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ export const SIGNATURES = {
'confidentialTransferFrom(address,address,bytes32)',
'confidentialTransferFromAndCall(address,address,bytes32,bytes,bytes)',
'confidentialTransferFromAndCall(address,address,bytes32,bytes)',
'contractURI()',
'decimals()',
'isOperator(address,address)',
'name()',
'setOperator(address,uint48)',
'symbol()',
],
ERC7984ContractURI: ['contractURI()'],
ERC7984ERC20Wrapper: ['underlying()', 'unwrap(address,address,bytes32,bytes)', 'wrap(address,uint256)'],
ERC7984RWA: [
'blockUser(address)',
Expand Down
7 changes: 1 addition & 6 deletions test/token/ERC7984/ERC7984.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import hre, { ethers, fhevm } from 'hardhat';

const name = 'ConfidentialFungibleToken';
const symbol = 'CFT';
const uri = 'https://example.com/metadata';

/* eslint-disable no-unexpected-multiline */
describe('ERC7984', function () {
beforeEach(async function () {
const accounts = await ethers.getSigners();
const [holder, recipient, operator] = accounts;

const token = await ethers.deployContract('$ERC7984Mock', [name, symbol, uri]);
const token = await ethers.deployContract('$ERC7984Mock', [name, symbol]);
this.accounts = accounts.slice(3);
this.holder = holder;
this.recipient = recipient;
Expand All @@ -41,10 +40,6 @@ describe('ERC7984', function () {
await expect(this.token.symbol()).to.eventually.equal(symbol);
});

it('sets the uri', async function () {
await expect(this.token.contractURI()).to.eventually.equal(uri);
});

it('decimals is 6', async function () {
await expect(this.token.decimals()).to.eventually.equal(6);
});
Expand Down
3 changes: 1 addition & 2 deletions test/token/ERC7984/ERC7984Votes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import { ethers, fhevm } from 'hardhat';

const name = 'ConfidentialFungibleTokenVotes';
const symbol = 'CFT';
const uri = 'https://example.com/metadata';

describe('ERC7984Votes', function () {
beforeEach(async function () {
const accounts = await ethers.getSigners();
const [holder, recipient, operator] = accounts;

const token = await ethers.deployContract('$ERC7984VotesMock', [name, symbol, uri]);
const token = await ethers.deployContract('$ERC7984VotesMock', [name, symbol]);

this.accounts = accounts.slice(3);
this.holder = holder;
Expand Down
Loading
Loading