zksync
zksync copied to clipboard
Supporting Contract Signatures for undeployed contracts
Currently L1-Accounts as Multisig are supported by checking the Contract Signature with EIP-1271 on the server and an L1 authorization when setting the pub key using setAuthPubkeyHash
.
But this requires a Contract to be deployed on L1 first. As a feature request, we would love to support signature verification without deploying the contract. This means as part of the contract signature we could pass the code of the deployment-transaction for L1. In order to verify we need to
- create a EVM
- deploy the tx-code
- call
isValidSignature
for the account.
To optimize we may cache the code or even better offer precompiled modules handling the logic directly based on the tx-data. ( For most Multisigs this could easily be implemented as Rust-Code)
But since there are 2 places we need to verify signatures (the Rust-Code and in the SolidityContract), this would also need to implemented this check in the verifyChangePubkeySignature
function in the smart contract.
We would love to support you, since this is an important feature, which would bring down deployment costs and would allow us to use multisigs in zksync without deploying them.
As a feature request, we would love to support signature verification without deploying the contract.
Great! We are implementing this feature right now.
Here how it would work:
You generate zkSync private key and compute your account address using CREATE2
spec where salt
is hashed zkSync pubkey_hash. Then you can set this pubkey_hash as signing key.
Prototype https://github.com/matter-labs/create2-example
This is awesome! I will test it out and let you know in case of any issues!
Yes, just tested it and this would indeed work for us! Tanks a lot. There is only one issue: Currently the salt is calculated from the signer key and the used to calc the address of the account.
Since we are deploying the gnosis safe, this would not work, because the safe will hash the initiator-data to the salt, which means in order to verify, we have to also add this as well.
I assume this is what the saltArg
does. But at the moment the gnosis safe simply uses exactly the opposite order.
// gnosis safe
bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
https://github.com/gnosis/safe-contracts/blob/development/contracts/proxies/GnosisSafeProxyFactory.sol#L47
So If we could have the saltArg as first argument, this would work with the gnosis safe. Do you see a chance switching the order here:
// zksync
bytes32 salt = keccak256(abi.encodePacked(_newPkHash,saltArg));
https://github.com/matter-labs/zksync/blob/create2-deployment/contracts/contracts/ZkSync.sol#L613
I just created a small PR to simply switch the order: https://github.com/matter-labs/zksync/pull/259
Ok, great that you reported it now, since we did not upgrade our contracts yet.
By the way I made a small change in the pull-request and actually tested it with the gnosis safe. (I added padding to 32bytes for the pub_key_hash when hashing, because this is how all the gnosis safes are deployed) Now It works! I generated a seed and from this the pub_key_hash. Deployed the GnosisSafeFactory, (which is the creatorAddress in this case) and used the codehas of the Proxy. Based on this I calculated the my account-address. and submitted a ChnagePubKey-tx, which was successfully executed and verified. Also transfer- and withdraw worked great.