Skip to main content

Deploy smart contracts

Learn everything you need to know to deploy contracts on Immutable zkEVM. As zkEVM offers EVM (Ethereum Virtual Machine) compatibility, smart contract development on zkEVM is almost identical to that on Ethereum.

For convenience, your quick access network details are here:

NetworkChain IDBlock ExplorerRPC Endpoint
Testnet13473https://explorer.testnet.immutable.com/https://rpc.testnet.immutable.com
Mainnet13371https://explorer.immutable.com/https://rpc.immutable.com

⚠️You may not be allowed to deploy your contract on Mainnet
There are two main ways to deploy contracts on Immutable zkEVM.
  1. You can deploy via Immutable Hub
  2. You can also deploy via code
If you are looking to deploy custom non-Immutable contracts via code on Immutable zkEVM Mainnet, your deployment wallet address needs to be specifically allowed. We have a waitlist process for this while we're in "Early Access". Please follow instructions here.

Please note, you DO NOT NEED TO BE ALLOWLISTED either of the following cases:
  • Deploy on Immutable zkEVM Testnet
  • You're deploying contracts via Immutable Hub

Articles in this tutorial includes:

Immutable zkEVM collection requirements

All collections deployed on Immutable's zkEVM must utilise the operator allowlist to protect content creator (eg: you, the game studio's) royalty fees and Immutable's 2% protocol fees.

This can be achieved through embedding the following into your smart contract collection designs:

For seamless implementation use or inherit Immutable's preset contracts tailored for gas-efficient creation of Web3 gaming assets on the zkEVM network. Immutable offers the following 3 preset contracts:

  • Recommended Presets for Web3 Games:
    • ImmutableERC721.sol - Multiple batch minting functions for optimised gas efficiency. Compatible with Minting API. Multiple batch minting functions for offering gas efficiencies for different Web3 gaming use cases.
    • ImmutableERC1155.sol. Semi-fungible tokens. Compatible with Minting API.
  • Alternative Presets:
    • ImmutableERC721MintByID.sol. Single batch minting function requiring game studio to specify token_id at time of mint. Optimised for gas, yet less gas efficient than ImmutableERC721.sol. Compatible with Minting API.

Minimally Required Standard

If the above options are not compatible with your game design, it is mandatory for your collection to inherit the OperatorAllowlistEnforced.sol contract and adding necessary overrides to approve and transfer functions, allowing your collection to interact with the OperatorAllowlist. OperatorAllowlistEnforced includes the modifier functions to identify compliant smart contracts for approvals and transfers, ensuring the preservation of content creators’ royalty fees and protocol fees in third-party marketplace transactions.

  • If your game design restricts your collections from importing Immutable's preset contracts, please note that your request for inclusion on the Mainnet's deployer allowlist may undergo additional processing time. Immutable will conduct thorough verification to ensure that your collections comply with our mandated standards, safeguarding content creators on the network. Thank you for your understanding and cooperation in ensuring Immutable's zkEVM network remains secure for our web3 gaming community.

Example contracts using OpenZeppelin's ERC721 and ERC1155 standards with the OperatorAllowlistEnforced contract are provided below:

Below is an example ClashOfCatsERC721 contract that inherits our OperatorAllowlistEnforced:

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.19;

import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {OperatorAllowlistEnforced} from '@imtbl/contracts/contracts/allowlist/OperatorAllowlistEnforced.sol';

contract ClashOfCatsERC721 is ERC721, Ownable, OperatorAllowlistEnforced {
constructor(
string memory name,
string memory symbol,
address operatorAllowlist_
) ERC721(name, symbol) Ownable() {
// OAL address is set in the constructor
_setOperatorAllowlistRegistry(operatorAllowlist_);
}

// Overrides _approve function to include `validateApproval` modifier for OAL
function _approve(
address to,
uint256 tokenId
) internal override(ERC721) validateApproval(to) {
super._approve(to, tokenId);
}

// Overrides setApprovalForAll function to include `validateApproval` modifier for OAL
function setApprovalForAll(
address operator,
bool approved
) public override(ERC721) validateApproval(operator) {
super.setApprovalForAll(operator, approved);
}

// Overrides _transfer function to include `validateTransfer` modifier for OAL
function _transfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721) validateTransfer(from, to) {
super._transfer(from, to, tokenId);
}
}
💡Operator Allowlist Checklist

Here is a simple collection operator allowlist checklist you should follow to ensure your game has no delays at launch:

  • Have you imported OperatorAllowlistEnforced.sol?
  • Have you overridden the transfer functions to include the `validateTransfer` modifier in order to check the allowlist for NFT transfers?
    • ERC721: `_transfer`
    • ERC721 Upgradable: `transferFrom`, `_safeTransfer`
    • ERC1155: `_safeTransferFrom`, `_safeBatchTransferFrom`
    • ERC1155 Upgradable: `_safeTransferFrom`, `_safeBatchTransferFrom`
  • Have you overridden the approve functions to include the `validateApproval` modifier in order to check the allowlist for NFT approvals?
    • ERC721: `_approve`, `setApprovalForAll`
    • ERC721 Upgradable: `approve`, `setApprovalForAll`
    • ERC1155: `setApprovalForAll`
    • ERC1155 Upgradable: `setApprovalForAll`
note

The use of the preset contracts accelerates integration with Immutable's ecosystem. If your studio has developed custom ERC721 or ERC1155 collections, ensure they adhere to their respective standards in addition to inheriting the OperatorAllowlistEnforced.sol contract, to safeguard compatibility with Immutable's ecosystem.