Common Utilities

Utilities for building on ZKsync Era

Web3Utils extension

Address modulo

Used for applying and undoing alias.

static let ADDRESS_MODULO = BigUInt(2).power(160)

L1 to L2 alias offset

Used for applying and undoing aliases on addresses during bridging from L1 to L2.

static let L1_TO_L2_ALIAS_OFFSET = "0x1111000000000000000000000000000000001111"

L1 fee estimation numerator

Used to when scaling gas limit for l1 transactions

IERC20

For interacting with native tokens.

let IERC20 = Web3Utils.IERC20

ZKsync Era main contract

let iZkSync = Web3.Utils.IZkSync

L1 messenger

Used for sending messages from ZKsync Era to Ethereum.

let IL1Messenger = Web3.Utils.IL1Messenger

L1 and L2 bridges

Bridge interface ABIs for L1 and L2.

let IL1Bridge = Web3.Utils.IL1Bridge
let IL2Bridge = Web3.Utils.IL2Bridge

applyL1ToL2Alias

Converts the address that submitted a transaction to the inbox on L1 to the msg.sender viewed on L2.

Returns the msg.sender of the L1->L2 transaction as the address of the contract that initiated the transaction.

More info
  1. During a normal transaction, if contract A calls contract B, the msg.sender is A.
  2. During L1->L2 communication, if an EOA X calls contract B, the msg.sender is X.
  3. During L1->L2 communication, if a contract A calls contract B, the msg.sender is applyL1ToL2Alias(A).

Inputs

ParameterTypeDescription
addressStringContract address.

Example

print(Web3Utils.applyL1ToL2Alias(address: "0x702942B8205E5dEdCD3374E5f4419843adA76Eeb"))
// l2ContractAddress = "0x813A42B8205E5DedCd3374e5f4419843ADa77FFC"

scaleGasLimit

Inputs

ParameterTypeDescription
gasBigUIntGas to scale.

Example

BigUInt = BigUInt(100_000)
BigUInt gasLimit = Web3Utils.scaleGasLimit(gas: baseLimit)

TransactionType

EIP712 transaction type

Constant representing an EIP712 transaction type.

case eip712 = 0x71

EIP712 structures

Collection of EIP712 structures with their types.

public func eip712types() -> [EIP712.`Type`] {
        return [
            ("txType", EIP712.UInt256(type.rawValue)),
            ("from", BigUInt(from!.addressData)),
            ("to", BigUInt(to.addressData)),
            ("gasLimit", gasLimit),
            ("gasPerPubdataByteLimit", eip712Meta?.gasPerPubdata as Any),
            ("maxFeePerGas", maxFeePerGas as Any),
            ("maxPriorityFeePerGas", maxPriorityFeePerGas as Any),
            ("paymaster", BigUInt(eip712Meta?.paymasterParams?.paymaster?.addressData ?? Data())),
            ("nonce", nonce),
            ("value", value as Any),
            ("data", data),
            ("factoryDeps", eip712Meta?.factoryDeps ?? []),
            ("paymasterInput", eip712Meta?.paymasterParams?.paymasterInput ?? Data())
        ]
    }

ZkSyncAddresses

ETH token layer 1

public static let EthAddress = "0x0000000000000000000000000000000000000000"

Contract deployer

public static let ContractDeployerAddress = "0x0000000000000000000000000000000000008006"

L1 messenger

public static let MessengerAddress = "0x0000000000000000000000000000000000008008"

Nonce holder

public static let NonceHolderAddress = "0x0000000000000000000000000000000000008003"

EthereumAddress extension

ETH token alias on ZKsync Era

static let L2EthTokenAddress = EthereumAddress("0x000000000000000000000000000000000000800a")!

ETH token layer 1

static let Default = EthereumAddress("0x0000000000000000000000000000000000000000")!

computeL2Create2Address

Generates a future-proof contract address using salt plus bytecode which allows determination of an address before deployment.

The ZKsync Era implementation is slightly different from Ethereum.

Inputs

ParameterTypeDescription
senderEthereumAddressSender address.
bytecodeDataOutput from zkSolc.
constructorDataABI encoded constructor arguments.
saltDataRandomization element.

Example

let result = ContractDeployer.computeL2Create2Address(EthereumAddress("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049")!,
                                                      bytecode: Data(hex: "0x010001cb6a6e8d5f6829522f19fa9568660e0a9cd53b2e8be4deb0a679452e41"),
                                                      constructor: Data(),
                                                      salt: Data())

computeL2CreateAddress

Generates a contract address from deployer's account and nonce.

Inputs

ParameterTypeDescription
senderEthereumAddressSender address.
nonceBigUIntSender nonce.

Example

let result = ContractDeployer.computeL2CreateAddress(EthereumAddress("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049")!, nonce: BigUInt(1))

estimateDefaultBridgeDepositL2Gas

Returns an estimation of L2 gas required for token bridging via the default ERC20 bridge.

Inputs

ParameterTypeDescription
providerL1Web3Ethers provider.
providerL2ZKsyncClientZKsync provider.
tokenEthereumAddressToken address.
amountBigUIntDeposit amount.
toAddressRecipient address.
fromEthereumAddressSender address.
gasPerPubdataByteBigNumberishCurrent gas per byte of pubdata, deffault 800 (optional).

getERC20DefaultBridgeData

Returns the calldata sent by an L1 ERC20 bridge to its L2 counterpart during token-bridging.

Inputs

ParameterTypeDescription
l1TokenAddressStringToken address on L1.
providerWeb3Provider.

verifySignature

Returns: true on verification success.

Inputs

ParameterTypeDescription
signatureStringSignature of the EIP-712 structures.
messageDataMessage to verify.
prefixedBoolIf true then add secure prefix EIP-712.

verifyTypedData

Returns: true on verification success.

Inputs

ParameterTypeDescription
domainEIP712DomainEIP712 domain.
typedDataSObject implementing EIP712 structure standard.
signatureStringSignature of the EIP-712 structures.

Made with ❤️ by the ZKsync Community