Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert to upgradeable and cloneable contracts #43

Merged
merged 5 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
12 changes: 11 additions & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,21 @@ jobs:
npm install
npm run test:e2e

- name: Run Zeto Tokens hardhat tests
- name: Run Zeto Tokens hardhat tests as upgradeable contracts
env:
PROVING_KEYS_ROOT: ${{ runner.temp }}/zeto-artifacts
CIRCUITS_ROOT: ${{ runner.temp }}/zeto-artifacts
working-directory: solidity
run: |
npm install
npm t

- name: Run Zeto Tokens hardhat tests as cloned contracts
env:
USE_FACTORY: true
PROVING_KEYS_ROOT: ${{ runner.temp }}/zeto-artifacts
CIRCUITS_ROOT: ${{ runner.temp }}/zeto-artifacts
working-directory: solidity
run: |
npm install
npm t
3 changes: 2 additions & 1 deletion solidity/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
node_modules
artifacts
cache
typechain-types
typechain-types
ignition/deployments
7 changes: 3 additions & 4 deletions solidity/contracts/erc20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ import "hardhat/console.sol";
/// - the hashes in the input and output match the `hash(value, salt, owner public key)` formula
/// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes
contract SampleERC20 is ERC20, Ownable {
constructor()
ERC20("Sample ERC20 token", "SampleERC20")
Ownable(msg.sender)
{
constructor(
address authority
) ERC20("Sample ERC20 token", "SampleERC20") Ownable(authority) {
_mint(msg.sender, 1000000 * 10 ** 18);
}

Expand Down
79 changes: 79 additions & 0 deletions solidity/contracts/factory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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.
pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {IZetoFungible} from "./lib/interfaces/zeto_fungible.sol";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not being used

import {IZetoFungibleInitializable} from "./lib/interfaces/zeto_fungible_initializable.sol";
import {IZetoNonFungibleInitializable} from "./lib/interfaces/zeto_nf_initializable.sol";
import {SampleERC20} from "./erc20.sol";

contract ZetoTokenFactory {
event ZetoTokenDeployed(address indexed zetoToken);

mapping(string => address) internal implementations;

constructor() {}

function registerImplementation(
string memory name,
address implementation
) public {
implementations[name] = implementation;
}

function deployZetoFungibleToken(
string memory name,
address authority,
address _depositVerifier,
address _withdrawVerifier,
address _verifier
) public returns (address) {
address instance = Clones.clone(implementations[name]);
require(
instance != address(0),
"Factory: failed to find implementation"
);
(IZetoFungibleInitializable(instance)).initialize(
authority,
_depositVerifier,
_withdrawVerifier,
_verifier
);
emit ZetoTokenDeployed(instance);
return instance;
}

function deployZetoNonFungibleToken(
string memory name,
address authority,
address _verifier
) public returns (address) {
address instance = Clones.clone(implementations[name]);
require(
instance != address(0),
"Factory: failed to find implementation"
);
(IZetoNonFungibleInitializable(instance)).initialize(
authority,
_verifier
);
emit ZetoTokenDeployed(instance);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels there are other information that could be useful to emit. But they can be added based on the use case in the future.

return instance;
}
}
22 changes: 22 additions & 0 deletions solidity/contracts/lib/interfaces/zeto_fungible.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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.
pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IZetoFungible {
function setERC20(IERC20 _erc20) external;
Copy link
Contributor

@Chengxuan Chengxuan Aug 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name of this file doesn't reflect it's mainly for supporting ERC20 contract anchoring, also, the interface is not used by multiple files as the existing abstract contract ZetoFungible seems to be sufficient for reusability. So it feels like we might not need this separate interface for now.

}
25 changes: 25 additions & 0 deletions solidity/contracts/lib/interfaces/zeto_fungible_initializable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// 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.
pragma solidity ^0.8.20;

interface IZetoFungibleInitializable {
function initialize(
address authority,
address _depositVerifier,
address _withdrawVerifier,
address _verifier
) external;
}
20 changes: 20 additions & 0 deletions solidity/contracts/lib/interfaces/zeto_nf_initializable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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.
pragma solidity ^0.8.20;

interface IZetoNonFungibleInitializable {
function initialize(address authority, address _verifier) external;
}
5 changes: 3 additions & 2 deletions solidity/contracts/lib/registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// limitations under the License.
pragma solidity ^0.8.20;

import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {SmtLib} from "@iden3/contracts/lib/SmtLib.sol";
import {PoseidonUnit2L, PoseidonUnit3L} from "@iden3/contracts/lib/Poseidon.sol";
import {Commonlib} from "./common.sol";
Expand All @@ -28,15 +29,15 @@ uint256 constant MAX_SMT_DEPTH = 64;
/// submitters can generate proofs of membership for the
/// accounts in a privacy-preserving manner.
/// @author Kaleido, Inc.
abstract contract Registry {
abstract contract Registry is OwnableUpgradeable {
SmtLib.Data internal _publicKeysTree;
using SmtLib for SmtLib.Data;

event IdentityRegistered(uint256[2] publicKey);

error AlreadyRegistered(uint256[2]);

constructor() {
function __Registry_init() internal onlyInitializing {
_publicKeysTree.initialize(MAX_SMT_DEPTH);
}

Expand Down
4 changes: 3 additions & 1 deletion solidity/contracts/lib/zeto_base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ abstract contract ZetoBase is ZetoCommon {
// maintains all the UTXOs
mapping(uint256 => UTXOStatus) internal _utxos;

constructor() ZetoCommon() {}
function __ZetoBase_init(address authority) internal onlyInitializing {
__ZetoCommon_init(authority);
}

/// @dev query whether a UTXO is currently spent
/// @return bool whether the UTXO is spent
Expand Down
7 changes: 5 additions & 2 deletions solidity/contracts/lib/zeto_common.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ pragma solidity ^0.8.20;

import {Commonlib} from "./common.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

/// @title A sample base implementation of a Zeto based token contract
/// @author Kaleido, Inc.
/// @dev Implements common functionalities of Zeto based tokens
abstract contract ZetoCommon is Ownable {
abstract contract ZetoCommon is OwnableUpgradeable {
event UTXOMint(uint256[] outputs, address indexed submitter);

event UTXOTransfer(
Expand Down Expand Up @@ -51,7 +52,9 @@ abstract contract ZetoCommon is Ownable {
// that did the locking.
mapping(bytes32 => address) internal lockedProofs;

constructor() Ownable(msg.sender) {}
function __ZetoCommon_init(address authority) internal onlyInitializing {
__Ownable_init(authority);
}

// should be called by escrow contracts that will use uploaded proofs
// to execute transactions, in order to prevent the proof from being used
Expand Down
9 changes: 6 additions & 3 deletions solidity/contracts/lib/zeto_fungible.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,24 @@ pragma solidity ^0.8.20;
import {Groth16Verifier_CheckHashesValue} from "./verifier_check_hashes_value.sol";
import {Groth16Verifier_CheckNullifierValue} from "./verifier_check_nullifier_value.sol";
import {Commonlib} from "./common.sol";
import {IZetoFungible} from "./interfaces/zeto_fungible.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

/// @title A sample implementation of a base Zeto fungible token contract
/// @author Kaleido, Inc.
/// @dev Defines the verifier library for checking UTXOs against a claimed value.
abstract contract ZetoFungible is Ownable {
abstract contract ZetoFungible is IZetoFungible, OwnableUpgradeable {
// depositVerifier library for checking UTXOs against a claimed value.
// this can be used in the optional deposit calls to verify that
// the UTXOs match the deposited value
Groth16Verifier_CheckHashesValue internal depositVerifier;

IERC20 internal erc20;

constructor(Groth16Verifier_CheckHashesValue _depositVerifier) {
function __ZetoFungible_init(
Groth16Verifier_CheckHashesValue _depositVerifier
) public onlyInitializing {
depositVerifier = _depositVerifier;
}

Expand Down
6 changes: 3 additions & 3 deletions solidity/contracts/lib/zeto_fungible_withdraw.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {Groth16Verifier_CheckInputsOutputsValue} from "./verifier_check_inputs_o
import {ZetoFungible} from "./zeto_fungible.sol";
import {Commonlib} from "./common.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

/// @title A sample implementation of a base Zeto fungible token contract
/// @author Kaleido, Inc.
Expand All @@ -31,10 +30,11 @@ abstract contract ZetoFungibleWithdraw is ZetoFungible {
// match the withdrawn value
Groth16Verifier_CheckInputsOutputsValue internal withdrawVerifier;

constructor(
function __ZetoFungibleWithdraw_init(
Groth16Verifier_CheckHashesValue _depositVerifier,
Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier
) ZetoFungible(_depositVerifier) {
) public onlyInitializing {
__ZetoFungible_init(_depositVerifier);
withdrawVerifier = _withdrawVerifier;
}

Expand Down
5 changes: 3 additions & 2 deletions solidity/contracts/lib/zeto_fungible_withdraw_nullifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ abstract contract ZetoFungibleWithdrawWithNullifiers is ZetoFungible {
// match the withdrawn value
Groth16Verifier_CheckNullifierValue internal withdrawVerifier;

constructor(
function __ZetoFungibleWithdrawWithNullifiers_init(
Groth16Verifier_CheckHashesValue _depositVerifier,
Groth16Verifier_CheckNullifierValue _withdrawVerifier
) ZetoFungible(_depositVerifier) {
) internal onlyInitializing {
__ZetoFungible_init(_depositVerifier);
withdrawVerifier = _withdrawVerifier;
}

Expand Down
3 changes: 2 additions & 1 deletion solidity/contracts/lib/zeto_nullifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ abstract contract ZetoNullifier is ZetoCommon {

error UTXORootNotFound(uint256 root);

constructor() ZetoCommon() {
function __ZetoNullifier_init(address authority) internal onlyInitializing {
__ZetoCommon_init(authority);
_commitmentsTree.initialize(MAX_SMT_DEPTH);
}

Expand Down
12 changes: 9 additions & 3 deletions solidity/contracts/zeto_anon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {ZetoBase} from "./lib/zeto_base.sol";
import {ZetoFungible} from "./lib/zeto_fungible.sol";
import {ZetoFungibleWithdraw} from "./lib/zeto_fungible_withdraw.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "hardhat/console.sol";

/// @title A sample implementation of a Zeto based fungible token with anonymity and no encryption
Expand All @@ -33,17 +34,22 @@ import "hardhat/console.sol";
/// - the sum of the input values match the sum of output values
/// - the hashes in the input and output match the `hash(value, salt, owner public key)` formula
/// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes
contract Zeto_Anon is ZetoBase, ZetoFungibleWithdraw {
contract Zeto_Anon is ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable {
Groth16Verifier_Anon internal verifier;

constructor(
function initialize(
address authority,
Groth16Verifier_CheckHashesValue _depositVerifier,
Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier,
Groth16Verifier_Anon _verifier
) ZetoBase() ZetoFungibleWithdraw(_depositVerifier, _withdrawVerifier) {
) public initializer {
__ZetoBase_init(authority);
__ZetoFungibleWithdraw_init(_depositVerifier, _withdrawVerifier);
verifier = _verifier;
}

function _authorizeUpgrade(address) internal override onlyOwner {}

/**
* @dev the main function of the contract.
*
Expand Down
12 changes: 9 additions & 3 deletions solidity/contracts/zeto_anon_enc.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {ZetoFungible} from "./lib/zeto_fungible.sol";
import {Registry} from "./lib/registry.sol";
import {Commonlib} from "./lib/common.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "hardhat/console.sol";

/// @title A sample implementation of a Zeto based fungible token with anonymity, and encryption
Expand All @@ -35,17 +36,22 @@ import "hardhat/console.sol";
/// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes
/// - the encrypted value in the input is derived from the receiver's UTXO value and encrypted with a shared secret using
/// the ECDH protocol between the sender and receiver (this guarantees data availability for the receiver)
contract Zeto_AnonEnc is ZetoBase, ZetoFungibleWithdraw {
contract Zeto_AnonEnc is ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable {
Groth16Verifier_AnonEnc internal verifier;

constructor(
function initialize(
address authority,
Groth16Verifier_CheckHashesValue _depositVerifier,
Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier,
Groth16Verifier_AnonEnc _verifier
) ZetoBase() ZetoFungibleWithdraw(_depositVerifier, _withdrawVerifier) {
) public initializer {
__ZetoBase_init(authority);
__ZetoFungibleWithdraw_init(_depositVerifier, _withdrawVerifier);
verifier = _verifier;
}

function _authorizeUpgrade(address) internal override onlyOwner {}

/**
* @dev the main function of the contract.
*
Expand Down
Loading
Loading