Skip to content

Commit 46dae6c

Browse files
committed
rename, implement
1 parent 1f31074 commit 46dae6c

17 files changed

+148
-1486
lines changed

packages/core/zama/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
"@openzeppelin/community-contracts": "git+https://github.com/OpenZeppelin/openzeppelin-community-contracts.git#de17c8e",
2626
"@openzeppelin/contracts": "^5.4.0",
2727
"@openzeppelin/contracts-upgradeable": "^5.4.0",
28+
"@openzeppelin/confidential-contracts": "^0.2.0",
29+
"@fhevm/solidity": "^0.7.0",
2830
"@types/node": "^20.0.0",
2931
"@types/semver": "^7.5.7",
3032
"ava": "^6.0.0",

packages/core/zama/src/api.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { CommonOptions } from './common-options';
2-
import type { ERC20Options } from './erc20';
2+
import type { ConfidentialFungibleOptions } from './confidentialFungible';
33
import {
4-
printERC20,
5-
defaults as erc20defaults,
6-
} from './erc20';
4+
printConfidentialFungible,
5+
defaults as confidentialFungibleDefaults,
6+
} from './confidentialFungible';
77

88
export interface WizardContractAPI<Options extends CommonOptions> {
99
/**
@@ -17,9 +17,9 @@ export interface WizardContractAPI<Options extends CommonOptions> {
1717
defaults: Required<Options>;
1818
}
1919

20-
export type ERC20 = WizardContractAPI<ERC20Options>;
20+
export type ConfidentialFungible = WizardContractAPI<ConfidentialFungibleOptions>;
2121

22-
export const erc20: ERC20 = {
23-
print: printERC20,
24-
defaults: erc20defaults,
22+
export const confidentialFungible: ConfidentialFungible = {
23+
print: printConfidentialFungible,
24+
defaults: confidentialFungibleDefaults,
2525
};

packages/core/zama/src/build-generic.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import type { ERC20Options } from './erc20';
2-
import { buildERC20 } from './erc20';
1+
import type { ConfidentialFungibleOptions } from './confidentialFungible';
2+
import { buildConfidentialFungible } from './confidentialFungible';
33
import type { Contract } from './contract';
44

55
export interface KindedOptions {
6-
ERC20: { kind: 'ERC20' } & ERC20Options;
6+
ConfidentialFungible: { kind: 'ConfidentialFungible' } & ConfidentialFungibleOptions;
77
}
88

99
export type GenericOptions = KindedOptions[keyof KindedOptions];
1010

1111
export function buildGeneric(opts: GenericOptions): Contract {
1212
switch (opts.kind) {
13-
case 'ERC20':
14-
return buildERC20(opts);
13+
case 'ConfidentialFungible':
14+
return buildConfidentialFungible(opts);
1515

1616
default: {
1717
// TODO: When other contract kinds are available, change the below to:
Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import test from 'ava';
22
import type { OptionsError } from '.';
3-
import { erc20 } from '.';
3+
import { confidentialFungible } from '.';
44

5-
import type { ERC20Options } from './erc20';
6-
import { buildERC20 } from './erc20';
5+
import type { ConfidentialFungibleOptions } from './confidentialFungible';
6+
import { buildConfidentialFungible } from './confidentialFungible';
77
import { printContract } from './print';
88

9-
function testERC20(title: string, opts: Partial<ERC20Options>) {
9+
function testConfidentialFungible(title: string, opts: Partial<ConfidentialFungibleOptions>) {
1010
test(title, t => {
11-
const c = buildERC20({
11+
const c = buildConfidentialFungible({
1212
name: 'MyToken',
1313
symbol: 'MTK',
14+
tokenURI: '',
1415
...opts,
1516
});
1617
t.snapshot(printContract(c));
@@ -20,48 +21,51 @@ function testERC20(title: string, opts: Partial<ERC20Options>) {
2021
/**
2122
* Tests external API for equivalence with internal API
2223
*/
23-
function testAPIEquivalence(title: string, opts?: ERC20Options) {
24+
function testAPIEquivalence(title: string, opts?: ConfidentialFungibleOptions) {
2425
test(title, t => {
2526
t.is(
26-
erc20.print(opts),
27+
confidentialFungible.print(opts),
2728
printContract(
28-
buildERC20({
29+
buildConfidentialFungible({
2930
name: 'MyToken',
3031
symbol: 'MTK',
32+
tokenURI: '',
3133
...opts,
3234
}),
3335
),
3436
);
3537
});
3638
}
3739

38-
testERC20('basic erc20', {});
40+
testConfidentialFungible('basic confidentialFungible', {});
3941

40-
testERC20('erc20 name is unicodeSafe', { name: 'MyTokeć' });
42+
testConfidentialFungible('confidentialFungible name is unicodeSafe', { name: 'MyTokeć' });
4143

42-
testERC20('erc20 preminted', {
44+
testConfidentialFungible('confidentialFungible preminted', {
4345
premint: '1000',
4446
});
4547

46-
testERC20('erc20 premint of 0', {
48+
testConfidentialFungible('confidentialFungible premint of 0', {
4749
premint: '0',
4850
});
4951

5052
function testPremint(scenario: string, premint: string, expectedError?: string) {
51-
test(`erc20 premint - ${scenario} - ${expectedError ? 'invalid' : 'valid'}`, async t => {
53+
test(`confidentialFungible premint - ${scenario} - ${expectedError ? 'invalid' : 'valid'}`, async t => {
5254
if (expectedError) {
5355
const error = t.throws(() =>
54-
buildERC20({
56+
buildConfidentialFungible({
5557
name: 'MyToken',
5658
symbol: 'MTK',
59+
tokenURI: '',
5760
premint,
5861
}),
5962
);
6063
t.is((error as OptionsError).messages.premint, expectedError);
6164
} else {
62-
const c = buildERC20({
65+
const c = buildConfidentialFungible({
6366
name: 'MyToken',
6467
symbol: 'MTK',
68+
tokenURI: '',
6569
premint,
6670
});
6771
t.snapshot(printContract(c));
@@ -84,32 +88,32 @@ testPremint(
8488
testPremint('e notation', '1e59');
8589
testPremint('e notation arithmetic overflow', '1e60', 'Amount would overflow uint256 after applying decimals');
8690

87-
testERC20('erc20 mintable', {
91+
testConfidentialFungible('confidentialFungible mintable', {
8892
mintable: true,
8993
access: 'ownable',
9094
});
9195

92-
testERC20('erc20 mintable with roles', {
96+
testConfidentialFungible('confidentialFungible mintable with roles', {
9397
mintable: true,
9498
access: 'roles',
9599
});
96100

97-
testERC20('erc20 votes', {
101+
testConfidentialFungible('confidentialFungible votes', {
98102
votes: true,
99103
});
100104

101-
testERC20('erc20 votes + blocknumber', {
105+
testConfidentialFungible('confidentialFungible votes + blocknumber', {
102106
votes: 'blocknumber',
103107
});
104108

105-
testERC20('erc20 votes + timestamp', {
109+
testConfidentialFungible('confidentialFungible votes + timestamp', {
106110
votes: 'timestamp',
107111
});
108112

109113

110114
// TODO test full
111115
/**
112-
testERC20('erc20 full', {
116+
testConfidentialFungible('confidentialFungible full', {
113117
premint: '2000',
114118
access: 'roles',
115119
burnable: true,
@@ -124,19 +128,20 @@ testERC20('erc20 full', {
124128
*/
125129

126130

127-
testAPIEquivalence('erc20 API default');
131+
testAPIEquivalence('confidentialFungible API default');
128132

129-
testAPIEquivalence('erc20 API basic', { name: 'CustomToken', symbol: 'CTK' });
133+
testAPIEquivalence('confidentialFungible API basic', { name: 'CustomToken', symbol: 'CTK', tokenURI: '' });
130134

131-
testAPIEquivalence('erc20 API full upgradeable', {
135+
testAPIEquivalence('confidentialFungible API full upgradeable', {
132136
name: 'CustomToken',
133137
symbol: 'CTK',
138+
tokenURI: 'http://example.com',
134139
premint: '2000',
135140
access: 'roles',
136141
mintable: true,
137142
votes: true,
138143
});
139144

140-
test('erc20 API assert defaults', async t => {
141-
t.is(erc20.print(erc20.defaults), erc20.print());
145+
test('confidentialFungible API assert defaults', async t => {
146+
t.is(confidentialFungible.print(confidentialFungible.defaults), confidentialFungible.print());
142147
});

packages/core/zama/src/erc20.ts renamed to packages/core/zama/src/confidentialFungible.ts

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import { toUint256, UINT256_MAX } from './utils/convert-strings';
1212
export const crossChainBridgingOptions = [false, 'custom', 'superchain'] as const;
1313
export type CrossChainBridging = (typeof crossChainBridgingOptions)[number];
1414

15-
export interface ERC20Options extends CommonOptions {
15+
export interface ConfidentialFungibleOptions extends CommonOptions {
1616
name: string;
1717
symbol: string;
18+
tokenURI: string;
1819
premint?: string;
1920
mintable?: boolean;
2021
/**
@@ -24,9 +25,10 @@ export interface ERC20Options extends CommonOptions {
2425
votes?: boolean | ClockMode;
2526
}
2627

27-
export const defaults: Required<ERC20Options> = {
28+
export const defaults: Required<ConfidentialFungibleOptions> = {
2829
name: 'MyToken',
2930
symbol: 'MTK',
31+
tokenURI: '',
3032
premint: '0',
3133
mintable: false,
3234
votes: false,
@@ -35,7 +37,7 @@ export const defaults: Required<ERC20Options> = {
3537
info: commonDefaults.info,
3638
} as const;
3739

38-
export function withDefaults(opts: ERC20Options): Required<ERC20Options> {
40+
export function withDefaults(opts: ConfidentialFungibleOptions): Required<ConfidentialFungibleOptions> {
3941
return {
4042
...opts,
4143
...withCommonDefaults(opts),
@@ -45,18 +47,18 @@ export function withDefaults(opts: ERC20Options): Required<ERC20Options> {
4547
};
4648
}
4749

48-
export function printERC20(opts: ERC20Options = defaults): string {
49-
return printContract(buildERC20(opts));
50+
export function printConfidentialFungible(opts: ConfidentialFungibleOptions = defaults): string {
51+
return printContract(buildConfidentialFungible(opts));
5052
}
5153

52-
export function buildERC20(opts: ERC20Options): ContractBuilder {
54+
export function buildConfidentialFungible(opts: ConfidentialFungibleOptions): ContractBuilder {
5355
const allOpts = withDefaults(opts);
5456

5557
const c = new ContractBuilder(allOpts.name);
5658

5759
const { info } = allOpts;
5860

59-
addBase(c, allOpts.name, allOpts.symbol);
61+
addBase(c, allOpts.name, allOpts.symbol, allOpts.tokenURI);
6062

6163
if (allOpts.premint) {
6264
addPremint(c, allOpts.premint);
@@ -66,24 +68,33 @@ export function buildERC20(opts: ERC20Options): ContractBuilder {
6668
// addMintable(c);
6769
// }
6870

69-
if (allOpts.votes) {
70-
const clockMode = allOpts.votes === true ? clockModeDefault : allOpts.votes;
71-
addVotes(c, clockMode);
72-
}
71+
// if (allOpts.votes) {
72+
// const clockMode = allOpts.votes === true ? clockModeDefault : allOpts.votes;
73+
// addVotes(c, clockMode);
74+
// }
7375

7476
setInfo(c, info);
7577

7678
return c;
7779
}
7880

79-
function addBase(c: ContractBuilder, name: string, symbol: string) {
80-
const ERC20 = {
81-
name: 'ERC20',
82-
path: '@openzeppelin/contracts/token/ERC20/ERC20.sol',
81+
function addBase(c: ContractBuilder, name: string, symbol: string, tokenURI: string) {
82+
const ConfidentialFungibleToken = {
83+
name: 'ConfidentialFungibleToken',
84+
path: '@openzeppelin/confidential-contracts/token/ConfidentialFungibleToken.sol',
8385
};
84-
c.addParent(ERC20, [name, symbol]);
85-
86-
c.addOverride(ERC20, functions._update);
86+
c.addParent(ConfidentialFungibleToken, [name, symbol, tokenURI]);
87+
88+
c.addImportOnly({
89+
name: 'euint64',
90+
path: '@fhevm/solidity/lib/FHE.sol',
91+
});
92+
c.addImportOnly({
93+
name: 'FHE',
94+
path: '@fhevm/solidity/lib/FHE.sol',
95+
});
96+
c.addOverride(ConfidentialFungibleToken, functions._update);
97+
c.addOverride(ConfidentialFungibleToken, functions.confidentialTotalSupply);
8798
}
8899

89100
export const premintPattern = /^(\d*)(?:\.(\d+))?(?:e(\d+))?$/;
@@ -117,7 +128,9 @@ function addPremint(
117128

118129
c.addConstructorArgument({ type: 'address', name: 'recipient' });
119130

120-
const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`;
131+
// TODO need to include decimals in the euint64. How?
132+
// const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`;
133+
const mintLine = `_mint(recipient, FHE.asEuint64(${units}));`;
121134

122135
c.addConstructorCode(mintLine);
123136
}
@@ -157,6 +170,7 @@ function addVotes(c: ContractBuilder, clockMode: ClockMode) {
157170
};
158171
c.addParent(ConfidentialFungibleTokenVotes);
159172
c.addOverride(ConfidentialFungibleTokenVotes, functions._update);
173+
c.addOverride(ConfidentialFungibleTokenVotes, functions.confidentialTotalSupply);
160174

161175
setClockMode(c, ConfidentialFungibleTokenVotes, clockMode);
162176
}
@@ -170,5 +184,10 @@ export const functions = defineFunctions({
170184
{ name: 'amount', type: 'euint64' },
171185
],
172186
},
173-
187+
confidentialTotalSupply: {
188+
kind: 'public' as const,
189+
mutability: 'view',
190+
args: [],
191+
returns: ['euint64'],
192+
},
174193
});

packages/core/zama/src/contract.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,23 @@ test('contract with one override', t => {
7070
{ name: 'amount', type: 'uint256' },
7171
],
7272
};
73-
Foo.addOverride(toContractReference('ERC20'), _beforeTokenTransfer);
73+
Foo.addOverride(toContractReference('ConfidentialFungible'), _beforeTokenTransfer);
7474
t.snapshot(printContract(Foo));
7575
});
7676

7777
test('contract with two overrides', t => {
7878
const Foo = new ContractBuilder('Foo');
79-
Foo.addOverride(toContractReference('ERC20'), _beforeTokenTransfer);
80-
Foo.addOverride(toContractReference('ERC20Snapshot'), _beforeTokenTransfer);
79+
Foo.addOverride(toContractReference('ConfidentialFungible'), _beforeTokenTransfer);
80+
Foo.addOverride(toContractReference('ConfidentialFungibleSnapshot'), _beforeTokenTransfer);
8181
t.snapshot(printContract(Foo));
8282
});
8383

8484
test('contract with two different overrides', t => {
8585
const Foo = new ContractBuilder('Foo');
8686

87-
Foo.addOverride(toContractReference('ERC20'), _beforeTokenTransfer);
87+
Foo.addOverride(toContractReference('ConfidentialFungible'), _beforeTokenTransfer);
8888
Foo.addOverride(toContractReference('OtherParent'), _beforeTokenTransfer);
89-
Foo.addOverride(toContractReference('ERC20'), _otherFunction);
89+
Foo.addOverride(toContractReference('ConfidentialFungible'), _otherFunction);
9090
Foo.addOverride(toContractReference('OtherParent'), _otherFunction);
9191
t.snapshot(printContract(Foo));
9292
});
@@ -101,7 +101,7 @@ test('contract with a modifier and override', t => {
101101
const Foo = new ContractBuilder('Foo');
102102
Foo.addModifier('whenNotPaused', _otherFunction);
103103

104-
Foo.addOverride(toContractReference('ERC20'), _otherFunction);
104+
Foo.addOverride(toContractReference('ConfidentialFungible'), _otherFunction);
105105
Foo.addOverride(toContractReference('OtherParent'), _otherFunction);
106106
t.snapshot(printContract(Foo));
107107
});

0 commit comments

Comments
 (0)