Coder Social home page Coder Social logo

era-contracts's Introduction

zkSync Era: Smart Contracts

Logo

zkSync Era is a layer 2 rollup that uses zero-knowledge proofs to scale Ethereum without compromising on security or decentralization. Since it's EVM compatible (Solidity/Vyper), 99% of Ethereum projects can redeploy without refactoring or re-auditing a single line of code. zkSync Era also uses an LLVM-based compiler that will eventually let developers write smart contracts in C++, Rust and other popular languages.

This repository contains both L1 and L2 zkSync smart contracts. For their description see the system overview.

Disclaimer

It is used as a submodule of a private repo. Compilation and test scripts should work without additional tooling, but others may not.

License

zkSync Era contracts are distributed under the terms of the MIT license.

See LICENSE-MIT for details.

Official Links

Disclaimer

zkSync Era has been through lots of testing and audits. Although it is live, it is still in alpha state and will go through more audits and bug bounties programs. We would love to hear our community's thoughts and suggestions about it! It is important to state that forking it now can potentially lead to missing important security updates, critical features, and performance improvements.

era-contracts's People

Contributors

agolajko avatar antond3 avatar aon avatar benceharomi avatar deniallugo avatar dimazhornyk avatar dnkolegov avatar emilluta avatar ischasny avatar jrchatruc avatar kelemeno avatar koloz193 avatar krauspt avatar ly0va avatar matias-gonz avatar mm-zk avatar neotheprogramist avatar onyxet avatar otani88 avatar pcaversaccio avatar perekopskiy avatar popzxc avatar saladerl avatar saxenism avatar shahar4 avatar stanislavbreadless avatar thomas-nguy avatar vladbochok avatar vladenysiuk avatar yorik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

era-contracts's Issues

Regarding fees

some dapp are charging much fess

Cant judge how fess will be return
Pls fix this

Introduce memory based `TransactionHelper`

Our TransactionHelper contract currently only supports calldata as input parameters. This makes it difficult to work with foundry libraries, and encode transactions on-chain.

function encodeHash(Transaction calldata _transaction) internal view returns (bytes32 resultHash) {

If I have a Transaction memory object, the library isn't helpful.

Use structs to remove being forced to compile via ir

As of today, using any of these contracts as a package results in the following issue.

Compiler run failed:
Error: Compiler error (/solidity/libsolidity/codegen/LValue.cpp:55):Stack too deep. Try compiling with `--via-ir` (cli) or the equivalent `viaIR: true` (standard JSON) while enabling the optimizer. Otherwise, try removing local variables.
CompilerError: Stack too deep. Try compiling with `--via-ir` (cli) or the equivalent `viaIR: true` (standard JSON) while enabling the optimizer. Otherwise, try removing local variables.
   --> lib/era-contracts/system-contracts/contracts/libraries/TransactionHelper.sol:133:38:
    |
133 |                 EfficientCall.keccak(_transaction.paymasterInput)

To get around this, you can instead use structs instead of so many variables.

You can only get this error if you try to compile the contracts using foundry, like so:

  1. Replace this with _anything
uint160 constant SYSTEM_CONTRACTS_OFFSET = {{SYSTEM_CONTRACTS_OFFSET}}; // 2^15
  1. Add a foundry.toml
echo -e "[profile.default]\nsrc = \"contracts\"" > foundry.toml
forge build

Add running tests to the `README`

I'm not sure how to run tests on this repo. Could we add a test key to the package.json, or at least tell users instructions are in each README.

To add more context, we need to update the CONTRIBUTING.md file entirely. It's not clear how this repo fits together. Is each folder in this repo self-contained? Can I even run the whole test suite across each directory?

The following folders likely need a README.md:

  1. l2-contracts
    I was unable to get this test suite to pass.

  2. l1-contracts
    I was unable to get this test suite to pass.

  3. system-contracts
    The system-contracts folder has a good README.md. I was able to successfully run and execute tests.

With how to run their test suite, and what the folders are intended to do/be.

L2StandardERC20 not being initialized correctly

Hello, I'm testing the ERC20 permit feature with USDC and DAI on the zkSync Era testnet. However, a permit signature created with the token name will not work and returns the error Invalid signature.

And it looks like the bridge token contract is not correctly initialized the ERC20PermitUpgradeable and only ERC20Upgradeable is initialized.

https://github.com/matter-labs/era-contracts/blob/main/zksync/contracts/bridge/L2StandardERC20.sol#L82

The DOMAIN_SEPARATOR() of the testnet DAI token will return 0x630ae2e0feb87df0136547b778ed1ad7bb1fdc555ac24d3a61b55432a339fe12 which is the exact value of the uninitialized domain separator.

Example codes to generate the same/uninitialized domain separator
https://gist.github.com/0xnakato/2c803385ac4c47c0455d6d0de105538f

TransactionHelper -> `generateBasicTransaction`

I'd like to make this issue on the npm zksync-contracts repo but I'm unsure as to where that is.

Problem

As of token, if I want to make a Transaction object (which I often do... Although I'm not sold on the name yet, but it's growing on me) I have to fill in this behemoth:

/// @notice Structure used to represent zkSync transaction.
struct Transaction {
    // The type of the transaction.
    uint256 txType;
    // The caller.
    uint256 from;
    // The callee.
    uint256 to;
    // The gasLimit to pass with the transaction.
    // It has the same meaning as Ethereum's gasLimit.
    uint256 gasLimit;
    // The maximum amount of gas the user is willing to pay for a byte of pubdata.
    uint256 gasPerPubdataByteLimit;
    // The maximum fee per gas that the user is willing to pay.
    // It is akin to EIP1559's maxFeePerGas.
    uint256 maxFeePerGas;
    // The maximum priority fee per gas that the user is willing to pay.
    // It is akin to EIP1559's maxPriorityFeePerGas.
    uint256 maxPriorityFeePerGas;
    // The transaction's paymaster. If there is no paymaster, it is equal to 0.
    uint256 paymaster;
    // The nonce of the transaction.
    uint256 nonce;
    // The value to pass with the transaction.
    uint256 value;
    // In the future, we might want to add some
    // new fields to the struct. The `txData` struct
    // is to be passed to account and any changes to its structure
    // would mean a breaking change to these accounts. In order to prevent this,
    // we should keep some fields as "reserved".
    // It is also recommended that their length is fixed, since
    // it would allow easier proof integration (in case we will need
    // some special circuit for preprocessing transactions).
    uint256[4] reserved;
    // The transaction's calldata.
    bytes data;
    // The signature of the transaction.
    bytes signature;
    // The properly formatted hashes of bytecodes that must be published on L1
    // with the inclusion of this transaction. Note, that a bytecode has been published
    // before, the user won't pay fees for its republishing.
    bytes32[] factoryDeps;
    // The input to the paymaster.
    bytes paymasterInput;
    // Reserved dynamic type for the future use-case. Using it should be avoided,
    // But it is still here, just in case we want to enable some additional functionality.
    bytes reservedDynamic;
}

It would be great if the TransactionHelper library came packed with a generateDefaultTransaction API for one to generate default transactions.

Potential Solution

The function could look as such:

/*
 * @param txType: 0x0, 0x1, 0x2, 0x3, 0x71, or 0xff
 */ 
function generateDefaultTransaction(uint8 txType) public returns(Transaction memory) {
  // proceed to populate the transaction with some good defaults..
}

This way, my API could be:

Transaction typeTwoTx = generateDefaultTransaction(2);
typeTwoTx.to = address(5);

Instead of having to populate everything myself.

Since this repo is intended to be a package, you need a floating point pragma

As of today, all the solidity typing using strict versioning, like so:

pragma solidity 0.8.20

While this is perfect for deploying contracts at a specific pragma, what needs to be understood is that a lot of the code in this repo is going to be used as a package as opposed to a stand-alone contract. For example, the zksync docs tell users to install the @matter-labs/zksync package (which, is this repo... sort of) in order to make account abstraction contracts that interact with the system contracts.

Because of this, we need this repo to have a floating pragma, like how openzeppelin or chainlink using floating pragma. Chainlink might be an even better example, because like zksync, they both deploy the contracts and use some as libraries for users.

Now, most auditors will sort of blindly say "oh, you have to use a strict pragma" but this is incorrect in this case because this is meant to be a dependency for smart contract builders building on zksync. If you said:

"Hey, all builders must use only version 0.8.20 of solidity" - then sure, you could do this, but I don't think that is the intention here, and that leads to a very poor developer experience anyways.

So, to summarize:

  1. Figure out which contracts are going to be used as libraries, and give them floating pragmas. You can even call them out in the comments of the file as to why they have floating pragmas
  2. When you send these to audit, tell them they must be floating pragmas because they are libraries, and the security researchers must consider that when working through them. This way, they can consider all the vulnerabilities associated with different versions of solidity.

proveL2MessageInclusion reverted "xx" code

image
zksync transaction: https://goerli.explorer.zksync.io/tx/0x6b43b036ef12cbd1d1ea99985b351c8d59d7cb22df2cbd210c2cbee48e56918b
I build an ERC20 bridge, but there are some messages that cannot authenticate messages from L2

here is params:
_blockNumber : 116164
_index: 1
_message: {txNumberInBlock: 562,sender: '0x1A09Bb36D7ed3eA5B1E4a53524586b45A63b503d',data: '0x11a2ccc1bfdf0d833e0be831646deeccf5a83da059f75b9e41211b38e33fea004c6767b0f150ede68e1e1d450000000000000000000000000000000000000000000000000de0b6b3a7640000' }
_proof: 0x926feac01291258985ffe1dc39fff171a7322f1743dfb59423bdf52104b34abd,0x82c55589ad70ca6e76c54a9b040ac73c566e788f76a205b10cabe4eb8a6ff4b0,0xe3697c7f33c31a9b0f0aeb8542287d0d21e8c4cf82163d0c44c7a98aa11aa111,0x199cc5812543ddceeddd0fc82807646a4899444240db2c0d2f20c3cceb5f51fa,0xe4733f281f18ba3ea8775dd62d2fcd84011c8c938f16ea5790fd29a03bf8db89,0x1798a1fd9c8fbb818c98cff190daa7cc10b6e5ac9716b4a2649f7c2ebcef2272,0x66d7c5983afe44cf15ea8cf565b34c6c31ff0cb4dd744524f7842b942d08770d,0xb04e5ee349086985f74b73971ce9dfe76bbed95c84906c5dffd96504e1e5396c,0xac506ecb5465659b3a927143f6d724f91d8d9c4bdb2463aee111d9aa869874db

Interaface abstraction

πŸ› Script Bug Report

πŸ“ Description

Provide a clear and concise description of the bug.

πŸ”„ Reproduction Steps

Steps to reproduce the behaviour

πŸ€” Expected Behavior

Describe what you expected to happen.

😯 Current Behavior

Describe what actually happened.

πŸ–₯️ Environment

Any relevant environment details.

πŸ“‹ Additional Context

Add any other context about the problem here. If applicable, add screenshots to help explain.

πŸ“Ž Log Output

Interaface abstraction  not proper

Update natspec for `IContractDeployer`

🌟 Feature Request

Reading the IContractDeployer interface, it's not clear what the parameters of each function do especially for important functions such as the create and create2 functions.

πŸ“ Description

Please add @param natspec annotations for what each of the parameters do.

πŸ€” Rationale

Deploying contracts is different on zkSync than on Ethereum. Because of that, when users dig deep into what's going on under the hood, it should be very clear what's going on. Right now, attempting to "peek under the hood" will be met with disappointment and more confusion.

  • What is input?
  • What is bytehash?
    etc

Script Bug Report for SystemContractsCaller.sol

πŸ› Script Bug Report

πŸ“ Description

The getFarCallABIWithEmptyFatPointer function in the code does not initialize the variable farCallAbiWithEmptyFatPtr before performing bitwise OR operations, which may lead to incorrect results.

πŸ”„ Reproduction Steps

  1. Call the getFarCallABIWithEmptyFatPointer function without initializing farCallAbiWithEmptyFatPtr.
  2. Perform bitwise OR operations on farCallAbiWithEmptyFatPtr using other variables.
  3. Check the value of farCallAbiWithEmptyFatPtr after the bitwise OR operations.

πŸ€” Expected Behavior

The variable farCallAbiWithEmptyFatPtr should be initialized to 0 before performing bitwise OR operations.

😯 Current Behavior

The variable farCallAbiWithEmptyFatPtr is not initialized, which may result in unexpected values after performing bitwise OR operations.

πŸ–₯️ Environment

  • Solidity version: 0.8.20

πŸ“‹ Additional Context

The uninitialized variable farCallAbiWithEmptyFatPtr could potentially lead to bugs or incorrect behavior in the code that uses this function. Initializing the variable to 0 before performing the bitwise OR operations would ensure that it starts with the correct value.

πŸ“Ž Log Output

N/A

[Proposal] Custom base token support

Summary:

Right now, only ETH is supported for hyperchain's base token. There are several use cases where a hyperchain would like to have a specific erc20 token as a base token rather than the native ETH.

In this issue, we are proposing to modify the "deposit" and "withdrawal" logic in the zksync contracts so that it could handle custom base token.

Problem definition

To understand the problem, we need to describe how the base token are currently "minted" and "burned" in layer 2.

The balance of the base token for all accounts is maintained by the L2EthToken.sol contract on L2.
The mint and burn can only be called by the bootloader.

Mint

The current "mint" mechanism is controlled by an event emitted by the zksync's diamond contract on L1

event NewPriorityRequest(
  uint256 txId,
  bytes32 txHash,
  uint64 expirationTimestamp,
  L2CanonicalTransaction transaction,
  bytes[] factoryDeps
);

With

 struct L2CanonicalTransaction {
        uint256 txType;
        uint256 from;
        uint256 to;
        uint256 gasLimit;
        uint256 gasPerPubdataByteLimit;
        uint256 maxFeePerGas;
        uint256 maxPriorityFeePerGas;
        uint256 paymaster;
        uint256 nonce;
        uint256 value;
        // In the future, we might want to add some
        // new fields to the struct. The `txData` struct
        // is to be passed to account and any changes to its structure
        // would mean a breaking change to these accounts. To prevent this,
        // we should keep some fields as "reserved".
        // It is also recommended that their length is fixed, since
        // it would allow easier proof integration (in case we will need
        // some special circuit for preprocessing transactions).
        uint256[4] reserved;
        bytes data;
        bytes signature;
        uint256[] factoryDeps;
        bytes paymasterInput;
        // Reserved dynamic type for the future use-case. Using it should be avoided,
        // But it is still here, just in case we want to enable some additional functionality.
        bytes reservedDynamic;
    }

The structure L2CanonicalTransaction contains a reserved field in which the first 32bytes are allocated to the valueToMint (let's call it reserved0 field)

A watcher monitors the Ethereum events emitted from the zksync’s diamond contract and creates a transaction on layer2 for each of this event recorded.

The bootloader, upon processing the transaction, will check the the value specified in the reserved0 field. In case this value is not null, will mint the specified value to the specified destination address.

Some safety checks are implemented to ensure that no value is created from thin air

  • The reserved0 field(value to mint) specified in the event is equal to the transaction msg.value . The zksync contract is used to store all the bridged ETH.

Total ETH mint = Total ETH stored in zksync contract account

  • To reduce the chance of failure, we also ensure that this value is enough to cover the transaction (cost & value) on L2.

Burn

The "burn" mechanism is controlled by the L2EthToken.sol contract on L2. By calling the withdrawal method, the amount specified in the transaction msg.value is burned from the sender account and a message is inserted to the L1_MESSENGER_CONTRACT. The message contains the withdrawal amount and the receiver address.

The eth_sender picks the message, includes it in a L2 transaction, and then encapsulates it in a block.

Upon executing the block on L1, the finalizeEthWithdrawal method from the zksync contract can be called on the block and process any messages it contains.

The ETH will be released to the specified receiver when processing the withdrawal message.

Proposed solution:

We follow the principle on "minimum change"

In this solution, 1 unit of token in L1 (locked) correspond to 1 unit of base token in L2 . The token contract on L1 should follow the ERC20 standard and have 18 decimals.

The only part that requires change in the solution is the "lock" and "unlock" mechanism on the L1 smart contract (mailbox) and the field β€œvalueToMint” be redefined.

The logic of β€œmint” and β€œburn” on layer2 remains the same, however it is crucial to implement an Oracle in the future to adjust the gas_price on layer2 according to the related price of the base token against Ethereum (could be a coefficient factor stored in DB and updated by a trusted oracle) as well a mechanism for the operator to convert the base token to ETH on L1 so that it can cover its costs.

We will only describe the changes needed in the smart contract in this issue.

The idea is to introduce a new "lock" and "unlock" mechanism at the Mailbox facet level and that instead of setting the valueToMint based on the msg.value, will use the value corresponding to the amount of ERC20 locked(safeTransfer) to the contract.

  • The msg.value is ignored and instead we will introduce a new input parameter uint256 _baseAmount. User can use this new parameter to specify the amount of token to be bridged.

https://github.com/matter-labs/era-contracts/pull/12/files#diff-df9164d8de562b3612626c482a4d9f1c014d796f1bd4d5dd42a210386a5bcf6dR263

  • In case of mint event, we have to explicitly transfer the ERC20 from the sender address to the contract address (lock)

https://github.com/matter-labs/era-contracts/pull/12/files#diff-df9164d8de562b3612626c482a4d9f1c014d796f1bd4d5dd42a210386a5bcf6dR245

  • In case of withdrawal event, we have to explicitly transfer the ERC20 from the contract address to the sender address

https://github.com/matter-labs/era-contracts/pull/12/files#diff-df9164d8de562b3612626c482a4d9f1c014d796f1bd4d5dd42a210386a5bcf6dR110

  • The logic to decide if we want to use an ERC20 or ETH as base token is defined by the baseTokenAddress value stored by the diamond proxy contract during initialization. This value represents the address of the ERC20 token to be used as base token. If it is zero, then we fallback to the default behavior which is to use ETH as base token

https://github.com/matter-labs/era-contracts/pull/12/files#diff-8c8f228bb83a30dbd6f369160e2016a869e01b68b1c106fc39196742f361d33bR50

  • The logic on L1WethBridge can be completely ignored. WETH can be treated as any ERC20 token

Points to be discussed

  • Should be make the changes in the existing contract or implement in new facets ?

It is possible to introduce a new facet CustomBaseMailBox and implement logic related to custom base token there instead of modifying the existing MailBox facet.

The script would need to be modified to deploy either CustomBaseMailBox or MailBox depending on the deployer use cases.

Pro : Non breaking change
Cons : More facets to maintains. Each changes in one facet would need to be duplicated in the other facet

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.