Implementation of an ERC4337 account enabling post-quantum security. The account lets us verify two signatures rather than only one. The goal is to enable post-quantum signatures while keeping the current ECDSA verification.
In order to run the tests, it is required to install the requirements for both Solidity and python (the python signer is used inside the Solidity tests):
make install
Then, run the tests as follows:
make test_opt
Note that Falcon key generation in python is a bit slow, and the test file computes it several times. In order to run tests separately:
forge test test/ZKNOX_ERC4337_account_K1_ETHFALCON.t.sol -vv
forge test test/ZKNOX_ERC4337_account_K1_FALCON.t.sol -vv
forge test test/ZKNOX_ERC4337_account_K1_MLDSA.t.sol -vv
forge test test/ZKNOX_ERC4337_account_K1_MLDSAETH.t.sol -vv
forge test test/ZKNOX_ERC4337_account_R1_ETHFALCON.t.sol -vv
forge test test/ZKNOX_ERC4337_account_R1_FALCON.t.sol -vv
forge test test/ZKNOX_ERC4337_account_R1_MLDSA.t.sol -vv
forge test test/ZKNOX_ERC4337_account_R1_MLDSAETH.t.sol -vv
ZKNOX_ECDSA.sol: verifies an ECDSA signature on Ethereum using the precompileecrecover,ERC7913P256Verifier.sol(from OpenZeppelin): verifies an ECDSA signature on P256 using the precompilep256verifiy.
ZKNOX_dilithium.sol: verifies a MLDSA signature,ZKNOX_ethdilithium.sol: verifies a MLDSAETH signature.ZKNOX_falcon.sol: verifies a FALCON signature.ZKNOX_ethfalcon.sol: verifies a ETHFALCON signature.
Each user owns a 4337 account contract which contains:
- a
pre_quantum_pubkeyinbytes; it can be an ethereum address (20 bytes) or a P256 point (64 bytes) - a
post_quantum_pubkeyinbytes; the address of aPKContractfor MLDSA(ETH), the public key bytes for FALCON - a
pre_quantum_logic_contract_addressreferring to one of the two pre-quantum fixed contracts above, - a
post_quantum_logic_contract_addressreferring to one of the two post-quantum fixed contracts above,
Note: for MLDSA, this requires an extra contract PKContract storing the MLDSA public key.
Because of the high gas amount, we decided to deploy the contracts on both L1 Sepolia and Arbitrum Sepolia.
The signature verifier contract addresses are fixed and deployed once for all. The address of the contracts are provided in the deployments/deployments.json file.
MLDSA public keys are large and we decided to write them inside contracts. Thus, each user needs to submit his (20kB) expanded MLDSA public key as an initialization step.
We provide an example of public key contract for both MLDSA and MLDSAETH, on the two testnets:
| Expanded PubKey Example for | Address on L1 Sepolia | Address on Arbitrum Sepolia |
|---|---|---|
| MLDSA | 0xCc28B19d743F3E139D6D8078B6600bad95CD7B2c | 0x8e130f25f30c9375971c9469f2adc30b6e91846f |
| MLDSAETH | 0x898Fec6390D8297BC0C92F834E4210a821ccD8B8 | 0xa854bf182dd854c7b85e35566aa5a46678e2be37 |
Note that these contracts do not correspond to the latest update of the contracts, but illustrate the structure of the contracts containing the public key.
Using the current contracts, the gas cost is the following:
| Contracts | MLDSA | MLDSA-ETH | FALCON | ETHFALCON |
|---|---|---|---|---|
| ECDSA-k1 | 8.39M | 5.12M | 4.06M | 1.69M |
| ECDSA-r1 | 8.40M | 5.13M | 4.07M | 1.70M |