From 5432c723e2f660316bf8138233ae628e59483000 Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Thu, 29 Aug 2024 22:24:47 -0400 Subject: [PATCH 1/4] Simplify factory's deploy method Signed-off-by: Jim Zhang --- solidity/contracts/factory.sol | 45 ++++++---- solidity/contracts/lib/verifier_anon.sol | 2 +- solidity/contracts/lib/verifier_anon_enc.sol | 2 +- .../lib/verifier_anon_enc_nullifier.sol | 2 +- ...ier_anon_enc_nullifier_non_repudiation.sol | 82 +++++++++---------- .../contracts/lib/verifier_anon_nullifier.sol | 2 +- .../lib/verifier_anon_nullifier_kyc.sol | 2 +- .../lib/verifier_check_hashes_value.sol | 2 +- .../verifier_check_inputs_outputs_value.sol | 2 +- .../lib/verifier_check_nullifier_value.sol | 2 +- solidity/contracts/lib/verifier_nf_anon.sol | 2 +- .../lib/verifier_nf_anon_nullifier.sol | 2 +- solidity/test/lib/deploy.ts | 12 ++- 13 files changed, 89 insertions(+), 70 deletions(-) diff --git a/solidity/contracts/factory.sol b/solidity/contracts/factory.sol index 78bccc2..38d6d9c 100644 --- a/solidity/contracts/factory.sol +++ b/solidity/contracts/factory.sol @@ -20,36 +20,45 @@ import {IZetoFungibleInitializable} from "./lib/interfaces/zeto_fungible_initial import {IZetoNonFungibleInitializable} from "./lib/interfaces/zeto_nf_initializable.sol"; contract ZetoTokenFactory { + struct InitArgs { + address implementation; + address depositVerifier; + address withdrawVerifier; + address verifier; + } + event ZetoTokenDeployed(address indexed zetoToken); - mapping(string => address) internal implementations; + mapping(string => InitArgs) internal implementations; constructor() {} function registerImplementation( string memory name, - address implementation + InitArgs memory implementation ) public { implementations[name] = implementation; } function deployZetoFungibleToken( string memory name, - address initialOwner, - address _depositVerifier, - address _withdrawVerifier, - address _verifier + address initialOwner ) public returns (address) { - address instance = Clones.clone(implementations[name]); + InitArgs memory args = implementations[name]; require( - instance != address(0), + args.implementation != address(0), "Factory: failed to find implementation" ); + address instance = Clones.clone(args.implementation); + require( + instance != address(0), + "Factory: failed to clone implementation" + ); (IZetoFungibleInitializable(instance)).initialize( initialOwner, - _depositVerifier, - _withdrawVerifier, - _verifier + args.depositVerifier, + args.withdrawVerifier, + args.verifier ); emit ZetoTokenDeployed(instance); return instance; @@ -57,17 +66,21 @@ contract ZetoTokenFactory { function deployZetoNonFungibleToken( string memory name, - address initialOwner, - address _verifier + address initialOwner ) public returns (address) { - address instance = Clones.clone(implementations[name]); + InitArgs memory args = implementations[name]; require( - instance != address(0), + args.implementation != address(0), "Factory: failed to find implementation" ); + address instance = Clones.clone(args.implementation); + require( + instance != address(0), + "Factory: failed to clone implementation" + ); (IZetoNonFungibleInitializable(instance)).initialize( initialOwner, - _verifier + args.verifier ); emit ZetoTokenDeployed(instance); return instance; diff --git a/solidity/contracts/lib/verifier_anon.sol b/solidity/contracts/lib/verifier_anon.sol index 6ef9172..47dc246 100644 --- a/solidity/contracts/lib/verifier_anon.sol +++ b/solidity/contracts/lib/verifier_anon.sol @@ -68,7 +68,7 @@ contract Groth16Verifier_Anon { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_anon_enc.sol b/solidity/contracts/lib/verifier_anon_enc.sol index 7e787cc..a9d676e 100644 --- a/solidity/contracts/lib/verifier_anon_enc.sol +++ b/solidity/contracts/lib/verifier_anon_enc.sol @@ -83,7 +83,7 @@ contract Groth16Verifier_AnonEnc { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[9] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol index be216ae..18647db 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol @@ -92,7 +92,7 @@ contract Groth16Verifier_AnonEncNullifier { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[12] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol index af6eb41..cab4aa5 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol @@ -46,65 +46,65 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { uint256 constant IC0x = 7150602979198858324531264522050588047187864437625863115811019715531635342988; uint256 constant IC0y = 18679352390540645799385538354080686740567422609949222164932202910206044361948; - uint256 constant IC1x = 20546933274967030575375764341048743544324686989399521428648988679453729672574; - uint256 constant IC1y = 12508114839394924272812953998788733726366166299611685224529406794282661918326; + uint256 constant IC1x = 20223737820803182000349268235929514427158015173398419989210846794808922069321; + uint256 constant IC1y = 19667519192504952779059431068168374697689187072685801450130109271314785916816; - uint256 constant IC2x = 4824487154794987582159170214878483637081677445844342466036965508921744954935; - uint256 constant IC2y = 20012603198977770575569235401254259856586296867286368963744054141596358017087; + uint256 constant IC2x = 7218856416869576295091037655873055759382316689150166584580005310257749626402; + uint256 constant IC2y = 18250824158316410204270915259713657522920241651507178610002708235185510464683; - uint256 constant IC3x = 13085357126364845655853054082065212176091907021303910631162840784306734614619; - uint256 constant IC3y = 18804105409926626067249386718984129501631713486331558650377019201942999164026; + uint256 constant IC3x = 10439404763847100272263651164703534229485312727099492374093433329301042860786; + uint256 constant IC3y = 11622072859931810063779349289989468302907213687444913890818865119671330403457; - uint256 constant IC4x = 12528747712399663633358900443201580207926260592781923514277748953386784545366; - uint256 constant IC4y = 15321444228429619370937074885438969957292587843245489130733239123958247484861; + uint256 constant IC4x = 3552958783616921573961765146209426612549096385286630602708070235513481501531; + uint256 constant IC4y = 7983004287008394591564704928605579735201397516705121349773346875253626793464; - uint256 constant IC5x = 15170475719758944115055889107023002588735327166378614199529086892326318914036; - uint256 constant IC5y = 8049620939170724410788843120022172935628332772087338494071162782553013962701; + uint256 constant IC5x = 7951915017279680503511105259632243418945970352099146353813397644881747832494; + uint256 constant IC5y = 15580187666685695375077645460858502959715552703766566567151236942633699459128; - uint256 constant IC6x = 663212334310334458163964230706247925833592395378902112591903654282088356896; - uint256 constant IC6y = 18754096412278896828863969347540361991262912756002947341277567135884137505700; + uint256 constant IC6x = 3810270046381397249153853319380867614609141932721597496641486068943447688518; + uint256 constant IC6y = 1789454555200419624433391404653719772125697252632300424422488567482953480839; - uint256 constant IC7x = 20346276952621247154598337223390816957539156326029095923114626385997849044836; - uint256 constant IC7y = 14162941292712917832463365746473687309497470625202464394839847050411947997730; + uint256 constant IC7x = 16582813285159387606825357695015456733307275683978941475967473789385465564139; + uint256 constant IC7y = 3370584196021878105671518949045188232217596798052799318361611555383941238644; - uint256 constant IC8x = 9248410646176563087034094961520748988428755370925933675211425461428345682132; - uint256 constant IC8y = 16296459388365501491563324106975466555396912797798729190644235870219784844785; + uint256 constant IC8x = 6410335958983016577852137704582430672625504797739898593884922605316966411317; + uint256 constant IC8y = 3561862755304133383761205380693974589872824992821334084854993222686099463287; - uint256 constant IC9x = 9083178110926851007296941420083669034008805783810176535662907367069262727367; - uint256 constant IC9y = 15272763540483910405229167164610099740544044456470363583487218543845277099600; + uint256 constant IC9x = 141988548012661067741546583487301665549799271673511121018755490875713551541; + uint256 constant IC9y = 11381489344212088827476994843766826329038542391607626896308015896573859623397; - uint256 constant IC10x = 6354539810570543825451702405001201431078418348494468217519344348456480113941; - uint256 constant IC10y = 14540363042032996638579967445622113233183047698171994701106413211929582200504; + uint256 constant IC10x = 2400404699093079437844767864727773463595132175554480756228013854499052897743; + uint256 constant IC10y = 16641639829319720713179419428727890115364728294133162095260244114066308681409; - uint256 constant IC11x = 15402490451329192726419686867507693651971698735095781620032357680507202300189; - uint256 constant IC11y = 18776825231374543966149883553033553817834994082859635640079373756431539000683; + uint256 constant IC11x = 18819343891508230813261093280482339631274788730864531524665810946260398413656; + uint256 constant IC11y = 939232547935730618247481870142928145681722172369345232371161962470473621455; - uint256 constant IC12x = 16338362324500910711458540995499662519825721035310309481766476791493413746239; - uint256 constant IC12y = 129099945110516700528901469394272124510164422816290268103236030804276978710; + uint256 constant IC12x = 19857900065761502826857489987079136225805396737807491159881256000358449239287; + uint256 constant IC12y = 14866158318731160894408347837912771366289709323081067853939131732571761322111; - uint256 constant IC13x = 11686582902269214695960711960780724175103725174284777129365136927796869647584; - uint256 constant IC13y = 16554706279775398925299029296786737540004147995537952533299814336712439852546; + uint256 constant IC13x = 654111863936885718257781142757347689010710641411633200860925542163991689666; + uint256 constant IC13y = 11276189838628957949004554103071438492770960919007402030163410690856320771850; - uint256 constant IC14x = 1391059691151041573765539336288822522255681866074476156253345556778984687459; - uint256 constant IC14y = 16704486067549765602531907643704887579736996248257686347177482380766430723027; + uint256 constant IC14x = 18969339244741250740753343010366495968956160496467373979506746525890248084164; + uint256 constant IC14y = 16274901896353030323013083904924198681645770552447391614076698136484842443636; - uint256 constant IC15x = 153683678643759940797793591527517619064774215867646038050151398326850833641; - uint256 constant IC15y = 10230454976416116340677437871207060840790045686005977662254602253013714878079; + uint256 constant IC15x = 5364945303376219658991823159374369520315533888650937587824150006805793367435; + uint256 constant IC15y = 15362324963834315062007218005904228090931585348452894617514266495515429954814; - uint256 constant IC16x = 3441020770783390721678420247863897181109537666056397599894290091843736969820; - uint256 constant IC16y = 6055734993367315995358389133634934031147209478192955140864459573136358459493; + uint256 constant IC16x = 7706652216614464307929318948621370806407028558413501412600554293234571043615; + uint256 constant IC16y = 4833155926438490231386220605163689437125897398884350656367983521056280632956; - uint256 constant IC17x = 16527482750362549411008515901030842811912583605167601846885701091727174163211; - uint256 constant IC17y = 21585460817698485257775813166157933463370089150885624438358161246914839874341; + uint256 constant IC17x = 1149166998309009330377390731594951819957167640308447230581596039029228635856; + uint256 constant IC17y = 17144496829204247748601976511350134750390256256716017203573337962163783928337; - uint256 constant IC18x = 5160955003840090131394114139067065035981538497817208563069514645767377705530; - uint256 constant IC18y = 4181642833667505155381399863468629907868977089312944758512189096196173663418; + uint256 constant IC18x = 9682269424428793097631391573982450090008352352784483866555904822950699832063; + uint256 constant IC18y = 7320838209204172545348024044818590112291242261458837363572039110259358463391; - uint256 constant IC19x = 4948442373592038976616201519852321320214615187307434803062754967096074408052; - uint256 constant IC19y = 14438208973905067256163771533917323300141311808685588768679512426522803920513; + uint256 constant IC19x = 1605487566693008705655072065911584353872368504749215742640417657776546622076; + uint256 constant IC19y = 2308043445104009725610511269022057743503782008796761536470885918528911939324; - uint256 constant IC20x = 21457772000319313553189685943142214457813393234972252846551500469611496162749; - uint256 constant IC20y = 11933932056971968632710667592027741826157658464631123816752425793753877842729; + uint256 constant IC20x = 2240609051444145211347356467283693175838292400028588894056540660459977622330; + uint256 constant IC20y = 1655940193015866774646205663901575824326740364428355076410141345515995005827; uint256 constant IC21x = 4853016079991973626530212093282440895734792373602971804488540915961627345640; uint256 constant IC21y = 7414374958276543278011110955360778512607526840415566794056500103235098338046; @@ -146,7 +146,7 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[30] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_anon_nullifier.sol b/solidity/contracts/lib/verifier_anon_nullifier.sol index 710950c..0c99b01 100644 --- a/solidity/contracts/lib/verifier_anon_nullifier.sol +++ b/solidity/contracts/lib/verifier_anon_nullifier.sol @@ -77,7 +77,7 @@ contract Groth16Verifier_AnonNullifier { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[7] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_anon_nullifier_kyc.sol b/solidity/contracts/lib/verifier_anon_nullifier_kyc.sol index 23c24d9..980cbe2 100644 --- a/solidity/contracts/lib/verifier_anon_nullifier_kyc.sol +++ b/solidity/contracts/lib/verifier_anon_nullifier_kyc.sol @@ -80,7 +80,7 @@ contract Groth16Verifier_AnonNullifierKyc { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[8] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_check_hashes_value.sol b/solidity/contracts/lib/verifier_check_hashes_value.sol index f837377..825874c 100644 --- a/solidity/contracts/lib/verifier_check_hashes_value.sol +++ b/solidity/contracts/lib/verifier_check_hashes_value.sol @@ -62,7 +62,7 @@ contract Groth16Verifier_CheckHashesValue { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[2] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_check_inputs_outputs_value.sol b/solidity/contracts/lib/verifier_check_inputs_outputs_value.sol index 1b9945d..9c0da51 100644 --- a/solidity/contracts/lib/verifier_check_inputs_outputs_value.sol +++ b/solidity/contracts/lib/verifier_check_inputs_outputs_value.sol @@ -68,7 +68,7 @@ contract Groth16Verifier_CheckInputsOutputsValue { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_check_nullifier_value.sol b/solidity/contracts/lib/verifier_check_nullifier_value.sol index 985c7c6..6f52468 100644 --- a/solidity/contracts/lib/verifier_check_nullifier_value.sol +++ b/solidity/contracts/lib/verifier_check_nullifier_value.sol @@ -77,7 +77,7 @@ contract Groth16Verifier_CheckNullifierValue { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[7] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_nf_anon.sol b/solidity/contracts/lib/verifier_nf_anon.sol index f2c2c3f..5b562d0 100644 --- a/solidity/contracts/lib/verifier_nf_anon.sol +++ b/solidity/contracts/lib/verifier_nf_anon.sol @@ -62,7 +62,7 @@ contract Groth16Verifier_NfAnon { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[2] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/contracts/lib/verifier_nf_anon_nullifier.sol b/solidity/contracts/lib/verifier_nf_anon_nullifier.sol index 79cf3d8..ecb777e 100644 --- a/solidity/contracts/lib/verifier_nf_anon_nullifier.sol +++ b/solidity/contracts/lib/verifier_nf_anon_nullifier.sol @@ -65,7 +65,7 @@ contract Groth16Verifier_NfAnonNullifier { function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[3] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { - if iszero(lt(v, q)) { + if iszero(lt(v, r)) { mstore(0, 0) return(0, 0x20) } diff --git a/solidity/test/lib/deploy.ts b/solidity/test/lib/deploy.ts index aa751b9..d0e078e 100644 --- a/solidity/test/lib/deploy.ts +++ b/solidity/test/lib/deploy.ts @@ -36,19 +36,25 @@ export async function deployZeto(tokenName: string) { const deployFunc = isFungible ? deployFungibleCloneable : deployNonFungibleCloneable; const result = await deployFunc(tokenName); ({ deployer, zetoImpl, erc20, args } = result as any); + const [deployerAddr, depositVerifier, withdrawVerifier, verifier] = args; // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); - const tx1 = await factory.connect(deployer).registerImplementation(tokenName, zetoImpl.target); + const tx1 = await factory.connect(deployer).registerImplementation(tokenName, { + implementation: zetoImpl.target, + depositVerifier, + withdrawVerifier, + verifier + } as any); await tx1.wait(); let tx2; if (isFungible) { - tx2 = await factory.connect(deployer).deployZetoFungibleToken(tokenName, ...args); + tx2 = await factory.connect(deployer).deployZetoFungibleToken(tokenName, deployerAddr); } else { - tx2 = await factory.connect(deployer).deployZetoNonFungibleToken(tokenName, ...args); + tx2 = await factory.connect(deployer).deployZetoNonFungibleToken(tokenName, deployerAddr); } const result1 = await tx2.wait(); From cda7682a2a6def4b79e19776d038c40991d23feb Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Thu, 29 Aug 2024 23:36:20 -0400 Subject: [PATCH 2/4] special treatment for non-fungible tokens Signed-off-by: Jim Zhang --- solidity/scripts/tokens/Zeto_Anon.ts | 4 ++-- solidity/scripts/tokens/Zeto_AnonEnc.ts | 4 ++-- solidity/scripts/tokens/Zeto_AnonEncNullifier.ts | 4 ++-- .../tokens/Zeto_AnonEncNullifierNonRepudiation.ts | 4 ++-- solidity/scripts/tokens/Zeto_AnonNullifier.ts | 4 ++-- solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts | 4 ++-- solidity/test/lib/deploy.ts | 12 +++++++----- 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/solidity/scripts/tokens/Zeto_Anon.ts b/solidity/scripts/tokens/Zeto_Anon.ts index 6d0d01c..7320553 100644 --- a/solidity/scripts/tokens/Zeto_Anon.ts +++ b/solidity/scripts/tokens/Zeto_Anon.ts @@ -25,9 +25,9 @@ export async function deployDependencies() { deployer, args: [ await deployer.getAddress(), + verifier.target, depositVerifier.target, - withdrawVerifier.target, - verifier.target + withdrawVerifier.target ] }; } \ No newline at end of file diff --git a/solidity/scripts/tokens/Zeto_AnonEnc.ts b/solidity/scripts/tokens/Zeto_AnonEnc.ts index dedf480..929a61b 100644 --- a/solidity/scripts/tokens/Zeto_AnonEnc.ts +++ b/solidity/scripts/tokens/Zeto_AnonEnc.ts @@ -25,9 +25,9 @@ export async function deployDependencies() { deployer, args: [ await deployer.getAddress(), + verifier.target, depositVerifier.target, - withdrawVerifier.target, - verifier.target + withdrawVerifier.target ] }; } \ No newline at end of file diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts index 2d79ab1..8ea1f6e 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts @@ -25,9 +25,9 @@ export async function deployDependencies() { deployer, args: [ await deployer.getAddress(), + verifier.target, depositVerifier.target, - withdrawVerifier.target, - verifier.target + withdrawVerifier.target ], libraries: { SmtLib: smtLib.target, diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts index 9f4b036..d07be02 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts @@ -25,9 +25,9 @@ export async function deployDependencies() { deployer, args: [ await deployer.getAddress(), + verifier.target, depositVerifier.target, - withdrawVerifier.target, - verifier.target + withdrawVerifier.target ], libraries: { SmtLib: smtLib.target, diff --git a/solidity/scripts/tokens/Zeto_AnonNullifier.ts b/solidity/scripts/tokens/Zeto_AnonNullifier.ts index 7704561..2535f84 100644 --- a/solidity/scripts/tokens/Zeto_AnonNullifier.ts +++ b/solidity/scripts/tokens/Zeto_AnonNullifier.ts @@ -25,9 +25,9 @@ export async function deployDependencies() { deployer, args: [ await deployer.getAddress(), + verifier.target, depositVerifier.target, - withdrawVerifier.target, - verifier.target + withdrawVerifier.target ], libraries: { SmtLib: smtLib.target, diff --git a/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts b/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts index 098ba21..6b7e06b 100644 --- a/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts +++ b/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts @@ -25,9 +25,9 @@ export async function deployDependencies() { deployer, args: [ await deployer.getAddress(), + verifier.target, depositVerifier.target, - withdrawVerifier.target, - verifier.target + withdrawVerifier.target ], libraries: { SmtLib: smtLib.target, diff --git a/solidity/test/lib/deploy.ts b/solidity/test/lib/deploy.ts index d0e078e..b35006c 100644 --- a/solidity/test/lib/deploy.ts +++ b/solidity/test/lib/deploy.ts @@ -36,19 +36,21 @@ export async function deployZeto(tokenName: string) { const deployFunc = isFungible ? deployFungibleCloneable : deployNonFungibleCloneable; const result = await deployFunc(tokenName); ({ deployer, zetoImpl, erc20, args } = result as any); - const [deployerAddr, depositVerifier, withdrawVerifier, verifier] = args; + const [deployerAddr, verifier, depositVerifier, withdrawVerifier] = args; // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); - const tx1 = await factory.connect(deployer).registerImplementation(tokenName, { + + const implInfo = { implementation: zetoImpl.target, - depositVerifier, - withdrawVerifier, + depositVerifier: depositVerifier || verifier, + withdrawVerifier: withdrawVerifier || verifier, verifier - } as any); + }; + const tx1 = await factory.connect(deployer).registerImplementation(tokenName, implInfo as any); await tx1.wait(); let tx2; if (isFungible) { From 36d397cdaf54bf3b0e189671bb96b2e5bedf5d8c Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Fri, 30 Aug 2024 12:06:34 -0400 Subject: [PATCH 3/4] Re-order initialize() args to match the deployed scripts Signed-off-by: Jim Zhang --- solidity/contracts/factory.sol | 4 ++-- solidity/contracts/zeto_anon.sol | 4 ++-- solidity/contracts/zeto_anon_enc.sol | 4 ++-- solidity/contracts/zeto_anon_enc_nullifier.sol | 4 ++-- .../contracts/zeto_anon_enc_nullifier_non_repudiation.sol | 4 ++-- solidity/contracts/zeto_anon_nullifier.sol | 4 ++-- solidity/contracts/zeto_anon_nullifier_kyc.sol | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/solidity/contracts/factory.sol b/solidity/contracts/factory.sol index 38d6d9c..a8570c8 100644 --- a/solidity/contracts/factory.sol +++ b/solidity/contracts/factory.sol @@ -56,9 +56,9 @@ contract ZetoTokenFactory { ); (IZetoFungibleInitializable(instance)).initialize( initialOwner, + args.verifier, args.depositVerifier, - args.withdrawVerifier, - args.verifier + args.withdrawVerifier ); emit ZetoTokenDeployed(instance); return instance; diff --git a/solidity/contracts/zeto_anon.sol b/solidity/contracts/zeto_anon.sol index 2699edf..cbf922e 100644 --- a/solidity/contracts/zeto_anon.sol +++ b/solidity/contracts/zeto_anon.sol @@ -39,9 +39,9 @@ contract Zeto_Anon is ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { function initialize( address initialOwner, + Groth16Verifier_Anon _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier, - Groth16Verifier_Anon _verifier + Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier ) public initializer { __ZetoBase_init(initialOwner); __ZetoFungibleWithdraw_init(_depositVerifier, _withdrawVerifier); diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index 76e4baa..6310f60 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -41,9 +41,9 @@ contract Zeto_AnonEnc is ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { function initialize( address initialOwner, + Groth16Verifier_AnonEnc _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier, - Groth16Verifier_AnonEnc _verifier + Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier ) public initializer { __ZetoBase_init(initialOwner); __ZetoFungibleWithdraw_init(_depositVerifier, _withdrawVerifier); diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index c4dad6d..2c8b653 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -43,9 +43,9 @@ contract Zeto_AnonEncNullifier is function initialize( address initialOwner, + Groth16Verifier_AnonEncNullifier _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier, - Groth16Verifier_AnonEncNullifier _verifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier ) public initializer { __ZetoNullifier_init(initialOwner); __ZetoFungibleWithdrawWithNullifiers_init( diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index 67140b0..ce30a31 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -55,9 +55,9 @@ contract Zeto_AnonEncNullifierNonRepudiation is function initialize( address initialOwner, + Groth16Verifier_AnonEncNullifierNonRepudiation _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier, - Groth16Verifier_AnonEncNullifierNonRepudiation _verifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier ) public initializer { __ZetoNullifier_init(initialOwner); __ZetoFungibleWithdrawWithNullifiers_init( diff --git a/solidity/contracts/zeto_anon_nullifier.sol b/solidity/contracts/zeto_anon_nullifier.sol index f6e87e7..a3c3e1e 100644 --- a/solidity/contracts/zeto_anon_nullifier.sol +++ b/solidity/contracts/zeto_anon_nullifier.sol @@ -47,9 +47,9 @@ contract Zeto_AnonNullifier is function initialize( address initialOwner, + Groth16Verifier_AnonNullifier _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier, - Groth16Verifier_AnonNullifier _verifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier ) public initializer { __ZetoNullifier_init(initialOwner); __ZetoFungibleWithdrawWithNullifiers_init( diff --git a/solidity/contracts/zeto_anon_nullifier_kyc.sol b/solidity/contracts/zeto_anon_nullifier_kyc.sol index 84c4434..427088c 100644 --- a/solidity/contracts/zeto_anon_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_nullifier_kyc.sol @@ -48,9 +48,9 @@ contract Zeto_AnonNullifierKyc is function initialize( address initialOwner, + Groth16Verifier_AnonNullifierKyc _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier, - Groth16Verifier_AnonNullifierKyc _verifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier ) public initializer { __Registry_init(); __ZetoNullifier_init(initialOwner); From a98f692c57e5bdd2a3f1f687090edf5ac53bd35a Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Fri, 30 Aug 2024 13:01:13 -0400 Subject: [PATCH 4/4] Addressing review comments Signed-off-by: Jim Zhang --- solidity/contracts/factory.sol | 34 +++++++-- solidity/test/factory.ts | 136 +++++++++++++++++++++++++++++++++ solidity/test/lib/deploy.ts | 4 +- 3 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 solidity/test/factory.ts diff --git a/solidity/contracts/factory.sol b/solidity/contracts/factory.sol index a8570c8..26b4172 100644 --- a/solidity/contracts/factory.sol +++ b/solidity/contracts/factory.sol @@ -20,7 +20,11 @@ import {IZetoFungibleInitializable} from "./lib/interfaces/zeto_fungible_initial import {IZetoNonFungibleInitializable} from "./lib/interfaces/zeto_nf_initializable.sol"; contract ZetoTokenFactory { - struct InitArgs { + // all the addresses needed by the factory to + // clone a Zeto token and initialize it. The + // "implementation" is used to clone the token, + // the rest of the addresses are used to initialize + struct ImplementationInfo { address implementation; address depositVerifier; address withdrawVerifier; @@ -29,14 +33,24 @@ contract ZetoTokenFactory { event ZetoTokenDeployed(address indexed zetoToken); - mapping(string => InitArgs) internal implementations; + mapping(string => ImplementationInfo) internal implementations; constructor() {} function registerImplementation( string memory name, - InitArgs memory implementation + ImplementationInfo memory implementation ) public { + require( + implementation.implementation != address(0), + "Factory: implementation address is required" + ); + require( + implementation.verifier != address(0), + "Factory: verifier address is required" + ); + // the depositVerifier and withdrawVerifier are optional + // for the non-fungible token implementations implementations[name] = implementation; } @@ -44,11 +58,21 @@ contract ZetoTokenFactory { string memory name, address initialOwner ) public returns (address) { - InitArgs memory args = implementations[name]; + ImplementationInfo memory args = implementations[name]; require( args.implementation != address(0), "Factory: failed to find implementation" ); + // check that the registered implementation is for a fungible token + // and has the required verifier addresses + require( + args.depositVerifier != address(0), + "Factory: depositVerifier address is required" + ); + require( + args.withdrawVerifier != address(0), + "Factory: withdrawVerifier address is required" + ); address instance = Clones.clone(args.implementation); require( instance != address(0), @@ -68,7 +92,7 @@ contract ZetoTokenFactory { string memory name, address initialOwner ) public returns (address) { - InitArgs memory args = implementations[name]; + ImplementationInfo memory args = implementations[name]; require( args.implementation != address(0), "Factory: failed to find implementation" diff --git a/solidity/test/factory.ts b/solidity/test/factory.ts new file mode 100644 index 0000000..981c901 --- /dev/null +++ b/solidity/test/factory.ts @@ -0,0 +1,136 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ethers, network } from 'hardhat'; +import { Signer } from 'ethers'; +import { expect } from 'chai'; + +describe("Zeto based fungible token with anonymity without encryption or nullifier", function () { + let deployer: Signer; + + before(async function () { + if (network.name !== 'hardhat') { + // accommodate for longer block times on public networks + this.timeout(120000); + } + [deployer] = await ethers.getSigners(); + }); + + it("attempting to register an implementation without the required implementation value should fail", async function () { + // we want to test the effectiveness of the factory contract + // to create clones of the Zeto implementation contract + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const factory = await Factory.deploy(); + await factory.waitForDeployment(); + + const implInfo = { + implementation: "0x0000000000000000000000000000000000000000", + verifier: "0x0000000000000000000000000000000000000000", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", + }; + await expect(factory.connect(deployer).registerImplementation("test", implInfo as any)).rejectedWith("Factory: implementation address is required"); + }); + + it("attempting to register an implementation without the required verifier value should fail", async function () { + // we want to test the effectiveness of the factory contract + // to create clones of the Zeto implementation contract + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const factory = await Factory.deploy(); + await factory.waitForDeployment(); + + const implInfo = { + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0x0000000000000000000000000000000000000000", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", + }; + await expect(factory.connect(deployer).registerImplementation("test", implInfo as any)).rejectedWith("Factory: verifier address is required"); + }); + + it("attempting to register an implementation with the required values should succeed", async function () { + // we want to test the effectiveness of the factory contract + // to create clones of the Zeto implementation contract + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const factory = await Factory.deploy(); + await factory.waitForDeployment(); + + const implInfo = { + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", + }; + await expect(factory.connect(deployer).registerImplementation("test", implInfo as any)).fulfilled; + }); + + it("attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail", async function () { + // we want to test the effectiveness of the factory contract + // to create clones of the Zeto implementation contract + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const factory = await Factory.deploy(); + await factory.waitForDeployment(); + + const implInfo = { + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", + }; + const tx1 = await factory.connect(deployer).registerImplementation("test", implInfo as any); + await tx1.wait(); + + await expect(factory.connect(deployer).deployZetoFungibleToken("test", await deployer.getAddress())).rejectedWith("Factory: depositVerifier address is required"); + }); + + it("attempting to deploy a fungible token but with a registered implementation that misses required withdrawVerifier should fail", async function () { + // we want to test the effectiveness of the factory contract + // to create clones of the Zeto implementation contract + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const factory = await Factory.deploy(); + await factory.waitForDeployment(); + + const implInfo = { + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + withdrawVerifier: "0x0000000000000000000000000000000000000000", + }; + const tx1 = await factory.connect(deployer).registerImplementation("test", implInfo as any); + await tx1.wait(); + + await expect(factory.connect(deployer).deployZetoFungibleToken("test", await deployer.getAddress())).rejectedWith("Factory: withdrawVerifier address is required"); + }); + + it("attempting to deploy a fungible token with a properly registered implementation should succeed", async function () { + // we want to test the effectiveness of the factory contract + // to create clones of the Zeto implementation contract + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const factory = await Factory.deploy(); + await factory.waitForDeployment(); + + const implInfo = { + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + }; + const tx1 = await factory.connect(deployer).registerImplementation("test", implInfo as any); + await tx1.wait(); + + await expect(factory.connect(deployer).deployZetoFungibleToken("test", await deployer.getAddress())).fulfilled; + }); +}); \ No newline at end of file diff --git a/solidity/test/lib/deploy.ts b/solidity/test/lib/deploy.ts index b35006c..6fdba83 100644 --- a/solidity/test/lib/deploy.ts +++ b/solidity/test/lib/deploy.ts @@ -46,8 +46,8 @@ export async function deployZeto(tokenName: string) { const implInfo = { implementation: zetoImpl.target, - depositVerifier: depositVerifier || verifier, - withdrawVerifier: withdrawVerifier || verifier, + depositVerifier: depositVerifier || "0x0000000000000000000000000000000000000000", + withdrawVerifier: withdrawVerifier || "0x0000000000000000000000000000000000000000", verifier }; const tx1 = await factory.connect(deployer).registerImplementation(tokenName, implInfo as any);