Creating a smart account
This tutorial defines how smart accounts work in =nil; and outlines the different ways for creating a new smart account.
Definition
In =nil; a smart account is any smart contract that is able to pay for interactions with real-life users.
The traditional definition of a smart account in Ethereum mostly refers to externally-owned accounts (EOAs) that are secured via private keys and natively hold information about user's balances.
Smart accounts in =nil; differ from this definition. A =nil; smart account is always a smart contract, and it must be deployed as such. The smart account handles all the usual functionalities (e.g., authenticating requests) but it can also include complex logic such as multi-sig operations.
This means that in almost all cases an external message has to go through a smart account that signs the message and assigns a value to it. The message is only forwarded to its target smart contract for execution only after this process is complete.
It is possible to send funds to an address where a contract is supposed to be deployed. These funds will be stored at that address until the contract is finally deployed, at which point the contract will be able to access them.
Funds sent to an address without a deployed contract are safe, and another party cannot claim them by deploying another contract before the owners of the funds is able to deploy their own contract.
Pre-built and custom smart accounts
Because any smart contract can be a smart account. there is a distinction between pre-built and custom smart accounts.
A pre-built smart account is provided as part of =nil;. Such a smart account includes essential smart account functionalities as well as pre-defined constructor bytecode. The =nil; developer tools provide several ways of deploying pre-built smart accounts such as the nil smart-account new
=nil; CLI command.
Presently, only one type of pre-built smart accounts is available. Additional types of pre-built smart accounts are WIP.
As pre-built smart accounts are provided as part of =nil; they are guaranteed to be valid and tested. An audit process for pre-built smart accounts is currently under consideration.
A custom smart account is any smart contract written by a user. This contract can support any flow permitted by Solidity code such as multi-sig authorization or token vesting. Custom smart accounts can be deployed just like any other smart contract.
New smart account creation
Via the =nil; CLI
The =nil; CLI offers a quick and convenient way to create a new smart account:
nil smart-account new --salt SALT
This will produce the following response:
Contract NEW_SMART_ACCOUNT_ADDRESS balance is topped up by 10000000
New smart account address: NEW_SMART_ACCOUNT_ADDRESS
This smart account essentially acts as a typical EOA: it supports basic asset management and authentication operations. The smart account should also be initialized with an initial balance (which is also seen in the initial command response). Send the following request to check this:
nil smart-account balance
The smart account can be 'topped up' by using the smart-account top-up AMOUNT
command.
The smart-account new
and the smart-account top-up
commands only work in the =nil; devnet. The process for attaining tokens and 'topping up' an address will be different in the production network.
Via the client library
The Nil.js
client library exposes the SmartAccountV1
class that allows for quickly creating and deploying a new smart account:
import { HttpTransport, PublicClient, generateSmartAccount } from "@nilfoundation/niljs";
const client = new PublicClient({
transport: new HttpTransport({
endpoint: RPC_ENDPOINT,
}),
shardId: 1,
});
const smartAccount = await generateSmartAccount({
shardId: 1,
rpcEndpoint: RPC_ENDPOINT,
faucetEndpoint: FAUCET_ENDPOINT,
});
This example initializes a new smart account. provides it with a Signer
and requests a 'top up' to the smart account address. The smart account is then deployed.
When using the client library, seqno
defaults to 0
for every message sent via the smart account. If too many messages are sent at the same time with this seqno
, they will fail. To avoid this issue, set the seqno
manually whenever using the smart account:
smartAccount.sendMessage({
...
seqno: SEQNO,
...
})