Skip to main content
When building smart contracts on Abstract, you often need to interact directly with system contracts to perform operations, such as:

Installing system contracts

To use system contracts into your smart contracts, install the @matterlabs/zksync-contracts package. forge install matter-labs/era-contracts
npm install @matterlabs/zksync-contracts
Then, import the system contracts into your smart contract:
// Example imports:
import "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IAccount.sol";
import { TransactionHelper } from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/TransactionHelper.sol";
import { BOOTLOADER_FORMAL_ADDRESS } from "@matterlabs/zksync-contracts/l2/system-contracts/Constants.sol";

Available System Contract Helper Libraries

A set of libraries also exist alongside the system contracts to help you interact with them more easily.
NameDescription
EfficientCall.solPerform ultra-efficient calls using zkEVM-specific features.
RLPEncoder.solRecursive-length prefix (RLP) encoding functionality.
SystemContractHelper.solLibrary used for accessing zkEVM-specific opcodes, needed for the development of system contracts.
SystemContractsCaller.solAllows calling contracts with the isSystem flag. It is needed to call ContractDeployer and NonceHolder.
TransactionHelper.solUsed to help custom smart contract accounts to work with common methods for the Transaction type.
UnsafeBytesCalldata.solProvides a set of functions that help read data from calldata bytes.
Utils.solCommon utilities used in Abstract system contracts.

System contract libraries source code

View all the source code for the system contract libraries.

The isSystem Flag

Each transaction can contain an isSystem flag that indicates whether the transaction intends to use a system contract’s functionality. Specifically, this flag needs to be true when interacting with the ContractDeployer or the NonceHolder system contracts. To make a call with this flag, use the SystemContractsCaller library, which exposes functions like systemCall, systemCallWithPropagatedRevert, and systemCallWithReturndata.
import {SystemContractsCaller} from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/SystemContractsCaller.sol";
import {NONCE_HOLDER_SYSTEM_CONTRACT, INonceHolder} from "@matterlabs/zksync-contracts/l2/system-contracts/Constants.sol";
import {TransactionHelper} from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/TransactionHelper.sol";

function validateTransaction(
    bytes32,
    bytes32,
    Transaction calldata _transaction
) external payable onlyBootloader returns (bytes4 magic) {

    // Increment nonce during validation
    SystemContractsCaller.systemCallWithPropagatedRevert(
        uint32(gasleft()),
        address(NONCE_HOLDER_SYSTEM_CONTRACT),
        0,
        abi.encodeCall(
            INonceHolder.incrementMinNonceIfEquals,
            (_transaction.nonce)
        )
    );

    // ... rest of validation logic here

}

Configuring Hardhat & Foundry to use isSystem

You can also enable the isSystem flag for your smart contract development environment.

Hardhat

Add enableEraVMExtensions: true within the settings object of the zksolc object in the hardhat.config.js file.
import { HardhatUserConfig } from "hardhat/config";
import "@matterlabs/hardhat-zksync";

const config: HardhatUserConfig = {
  zksolc: {
    version: "latest",
    settings: {
      // This is the current name of the "isSystem" flag
      enableEraVMExtensions: true, // Note: NonceHolder and the ContractDeployer system contracts can only be called with a special isSystem flag as true
    },
  },
  defaultNetwork: "abstractTestnet",
  networks: {
    abstractTestnet: {
      url: "https://api.testnet.abs.xyz",
      ethNetwork: "sepolia",
      zksync: true,
      verifyURL:
        "https://api-explorer-verify.testnet.abs.xyz/contract_verification",
    },
  },
  solidity: {
    version: "0.8.24",
  },
};

export default config;

Foundry

Add the is_system = true flag to the foundry.toml configuration file.
[profile.default]
src = 'src'
libs = ['lib']
fallback_oz = true
is_system = true # Note: NonceHolder and the ContractDeployer system contracts can only be called with a special isSystem flag as true
mode = "3"

[etherscan]
abstractTestnet = { chain = "11124", url = "", key = ""} # You can replace these values or leave them blank to override via CLI
abstractMainnet = { chain = "2741", url = "", key = ""} # You can replace these values or leave them blank to override via CLI
I