Smart Contract Wallets
Learn how smart contract wallets are built following the IAccount standard on Abstract.
On Abstract, all accounts are smart contracts that implement the
IAccount interface. As outlined in the transaction flow,
the bootloader calls the functions of the smart contract account deployed at the tx.from
address for
each transaction that it processes.
Abstract maintains compatibility with popular EOA wallets from the Ethereum ecosystem (e.g. MetaMask) by converting them to the DefaultAccount system contract during the transaction flow. This contract acts as you would expect an EOA to act, with the added benefit of supporting paymasters.
Get Started with Smart Contract Wallets
Use our example repositories to quickly get started building smart contract wallets.
Or follow our video tutorial for a step-by-step guide to building a smart contract wallet.
YouTube Video: Build a Smart Contract Wallet on Abstract
IAccount Interface
The IAccount
interface defines the mandatory functions that a smart contract account must implement to be
compatible with Abstract. View source code ↗.
First, install the system contracts library:
Then, import and implement the IAccount
interface in your smart contract:
import {IAccount} from "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IAccount.sol";
contract SmartAccount is IAccount {
// Implement the interface (see docs below)
// validateTransaction
// executeTransaction
// executeTransactionFromOutside
// payForTransaction
// prepareForPaymaster
}
See the DefaultAccount contract for an example implementation.
Using system contracts
Learn more about how to use system contracts in Solidity.
validateTransaction
This function is called to determine whether or not the transaction should be executed (i.e. it validates the transaction). Typically, you would perform some kind of check in this step to restrict who can use the account. This function must:
- Increment the nonce for the account. See handling nonces for more information.
- Return
magic = ACCOUNT_VALIDATION_SUCCESS_MAGIC
if the transaction is valid and should be executed. - Should only be called by the bootloader contract (e.g. using an
onlyBootloader
modifier).
function validateTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable returns (bytes4 magic);
executeTransaction
This function is called if the validation step
returned the ACCOUNT_VALIDATION_SUCCESS_MAGIC
value. Consider:
- Using the EfficientCall library for executing transactions efficiently using zkEVM-specific features.
- Consider that the transaction may involve a contract deployment, in which case you should
use the ContractDeployer
system contract with the
isSystemCall
flag set to true. - Should only be called by the bootloader contract (e.g. using an
onlyBootloader
modifier).
function executeTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable;
executeTransactionFromOutside
This function should be used to initiate a transaction from the smart contract wallet by an external call. Accounts can implement this method to initiate a transaction on behalf of the account via L1 -> L2 communication.
function executeTransactionFromOutside(
Transaction calldata _transaction
) external payable;
payForTransaction
This function is called to pay the bootloader for the gas fee of the transaction.
It should only be called by the bootloader contract (e.g. using an onlyBootloader
modifier).
For convenience, there is a _transaction.payToTheBootloader()
function that can be used
to pay the bootloader for the gas fee.
function payForTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable;
prepareForPaymaster
Alternatively to payForTransaction
, if the transaction has a paymaster set,
you can use prepareForPaymaster
to ask the paymaster to sponsor the gas fee for the transaction.
It should only be called by the bootloader contract (e.g. using an onlyBootloader
modifier).
For convenience, there is a _transaction.processPaymasterInput()
function that can be used to prepare the
transaction for the paymaster.
function prepareForPaymaster(
bytes32 _txHash,
bytes32 _possibleSignedHash,
Transaction calldata _transaction
) external payable;
Deploying a Smart Contract Wallet
The ContractDeployer system contract has separate functions
for deploying smart contract wallets: createAccount
and create2Account
.
Differentiate deploying an account contract from deploying a regular contract by providing either of these function names when initializing a contract factory.
Sending Transactions from a Smart Contract Wallet
Use EIP-712 formatted transactions to submit transactions from a smart contract wallet. You must specify:
- The
from
field as the address of the deployed smart contract wallet. - Provide a
customData
object containing acustomSignature
that is not an empty string.
DefaultAccount Contract
The DefaultAccount
contract is a system contract that mimicks the behaviour of an EOA.
The bytecode of the contract is set by default for all addresses for which no other bytecodes are deployed.
DefaultAccount system contract
Learn more about the DefaultAccount system contract and how it works.
Smart Contract References
Was this page helpful?