SmartAccount

A flexible signer for various payloads using different secrets.

A SmartAccount is a signer which can be configured to sign various payloads using a provided secret. The secret can be in any form, allowing for flexibility when working with different account implementations. The SmartAccount is bound to a specific address and provides the ability to define custom method for populating transactions and custom signing method used for signing. It is compatible with web3py.Contract for deploying contracts/accounts and for interacting with contracts/accounts using provided ABI along with custom transaction signing logic.

__init__

Creates a SmartAccount instance with provided signer and provider. By default, uses sign_payload_with_ecdsa and sign_payload_with_multiple_ecdsa.

Inputs

ParameterTypeDescription
addressHexStrAddress of the smart account.
secretHexStrSecrets to be used for signing transactions.
providerWeb3The provider to connect to.
transaction_builderMethodImplementation of transaction builder (default is populate_transaction_ecdsa).
payload_signerMethodImplementation of signing (default is sign_payload_with_ecdsa).

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

get_address

Returns the address of the account.

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  address = account.get_address()

get_balance

Returns the balance of the account.

Inputs

NameDescription
block_tagThe block the balance should be checked on. committed, i.e. the latest processed one is the default option.
token_addressThe address of the token. ETH by default.

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  balance = account.get_balance()

get_all_balances

Returns all balances for confirmed tokens given by an account address.

Inputs and outputs

NameDescription
returnsZksAccountBalances with all account balances.

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  all_balances = account.get_all_balances()

get_deployment_nonce

Returns account's deployment nonce number.

Inputs and outputs

NameDescription
returnsThe deployment nonce number.

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  nonce = account.get_deployment_nonce()

populate_transaction

Populates the transaction tx using the provided transaction_builder function. If tx.from is not set, it sets the value from the get_address method which can be utilized in the transaction builder function.

Inputs

ParameterTypeDescription
txTransaction712The transaction that needs to be populated.

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  populated = account.populate_transaction(TxTransfer(
            from_=address_1,
            to=address_2,
            value=7_000_000_000,
            token=ADDRESS_DEFAULT
        ).tx712(0))

sign_transaction

Signs the transaction tx using the provided payload_signer function, returning the fully signed transaction. The populate_transaction method is called first to ensure that all necessary properties for the transaction to be valid have been populated.

Inputs

ParameterTypeDescription
txTransaction712The transaction that needs to be signed.

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  signed = account.sign_transaction(TxTransfer(
            from_=address_1,
            to=address_2,
            value=7_000_000_000,
            token=ADDRESS_DEFAULT
        ).tx712(0))

send_transaction

Sends tx to the Network. The sign_transaction is called first to ensure transaction is properly signed.

Inputs

ParameterTypeDescription
txTransaction712The transaction that needs to be sent.

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zksync = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  signed = account.send_transaction(TxTransfer(
            from_=address_1,
            to=address_2,
            value=7_000_000_000,
            token=ADDRESS_DEFAULT
        ).tx712(0))

withdraw

Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 network to the target account on L1 network.

Inputs

NameDescription
transactionWithdrawTransaction

Example

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3
from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder
from zksync2.core.types import WithdrawTransaction, ADDRESS_DEFAULT


ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

zk_web3 = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

account = SmartAccount(address_1, HexStr(private_key_1), zksync)

withdraw_tx_hash = account.withdraw(
    WithdrawTransaction(
        token=ADDRESS_DEFAULT, amount=Web3.to_wei(1, "ether")
    )
)

withdraw_receipt = zk_web3.zksync.wait_for_transaction_receipt(
    withdraw_tx_hash, timeout=240, poll_latency=0.5
)

Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token.

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3
from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder
from zksync2.core.types import WithdrawTransaction, ADDRESS_DEFAULT


ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

zk_web3 = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

account = SmartAccount(address_1, HexStr(private_key_1), zksync)

paymaster_address = zk_web3.to_checksum_address(HexStr("0x13D0D8550769f59aa241a41897D4859c87f7Dd46"))
token_address = zk_web3.to_checksum_address(HexStr("0x927488F48ffbc32112F1fF721759649A89721F8F"))

paymaster_params = PaymasterParams(
    **{
        "paymaster": paymaster_address,
        "paymaster_input": eth_web3.to_bytes(
            hexstr=PaymasterFlowEncoder(eth_web3).encode_approval_based(
                token_address, 1, b""
            )
        ),
    }
)

withdraw_tx_hash = account.withdraw(
    WithdrawTransaction(
        token=ADDRESS_DEFAULT, amount=Web3.to_wei(1, "ether"), paymaster_params=paymaster_params
    )
)

withdraw_receipt = zk_web3.zksync.wait_for_transaction_receipt(
    withdraw_tx_hash, timeout=240, poll_latency=0.5
)

transfer

For convenience, the Wallet class has transfer method, which can transfer ETH or any ERC20 token within the same interface.

Inputs and outputs

NameDescription
txTransferTransaction.
returnsA HexStr of transaction.

Example

Transfer ETH.

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder
from zksync2.core.types import TransferTransaction, ADDRESS_DEFAULT

if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zk_web3 = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  amount = 7_000_000_000
  tx_hash = account.transfer(TransferTransaction(to=Web3.to_checksum_address("TO_ADDRESS"),
  token_address=ADDRESS_DEFAULT,
  amount=amount))

  tx_receipt = zk_web3.zksync.wait_for_transaction_receipt(
    tx_hash, timeout=240, poll_latency=0.5
  )

Transfer ETH using paymaster to facilitate fee payment with an ERC20 token.

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3

from zksync2.account.smart_account import SmartAccount
from zksync2.module.module_builder import ZkSyncBuilder
from zksync2.core.types import TransferTransaction, ADDRESS_DEFAULT, PaymasterParams
from zksync2.manage_contracts.paymaster_utils import PaymasterFlowEncoder


if __name__ == "__main__":
  ZKSYNC_PROVIDER = "https://sepolia.era.zksync.dev"

  zk_web3 = ZkSyncBuilder.build(ZKSYNC_PROVIDER)

  account = SmartAccount(address_1, HexStr(private_key_1), zksync)

  paymaster_address = zk_web3.to_checksum_address("0x13D0D8550769f59aa241a41897D4859c87f7Dd46")
  token_address = zk_web3.to_checksum_address("0x927488F48ffbc32112F1fF721759649A89721F8F")


  paymaster_params = PaymasterParams(
            **{
                "paymaster": paymaster_address,
                "paymaster_input": eth_web3.to_bytes(
                    hexstr=PaymasterFlowEncoder(eth_web3).encode_approval_based(
                        token_address, 1, b""
                    )
                ),
            }
        )

  amount = 7_000_000_000
  tx_hash = account.transfer(
              TransferTransaction(
                  to=Web3.to_checksum_address("TO_ADDRESS"),
                  amount=amount,
                  paymaster_params=paymaster_params,
              )
          )

  tx_receipt = zk_web3.zksync.wait_for_transaction_receipt(
    tx_hash, timeout=240, poll_latency=0.5
  )

Made with ❤️ by the ZKsync Community