Creating a Smart Wallet

Pre-Requisites

  • Follow the system-setup guide.

Deploy a Smart Wallet

To deploy a smart wallet we need to do some steps to generate the wallet address, fund it and finally deploy the smart wallet. Here we are going to show you how to do that.

  1. Generate your smart wallet address. To do this you need to call the method getSmartWalletAddress on the SmartWalletFactory contract, it can be found in the enveloping repo under src/cli/compiled/SmartWalletFactory.json. You need to extract the abi from there and then use it to instantiate the contract with web3. Here is an example of how to do it:
         import Web3 from "web3";
    
         const web3 = new Web3(<RSK_NODE_ENDPOINT>);
    
         const smartWalletAddress = await new web3.eth.Contract(
             <SMART_WALLET_FACTORY_ABI>,
             <SMART_WALLET_FACTORY_ADDRESS>
         ).methods.getSmartWalletAddress(
             <RSK_ACCOUNT_ADDRESS>,
             <SMART_WALLET_RECOVERER>,
             <SMART_WALLET_INDEX>
         ).call();
    

    Where variables are:

    • RSK_NODE_ENDPOINT: the RSK node endpoint where is running (ex: http://localhost:4444).
    • SMART_WALLET_FACTORY_ABI: the smart wallet factory contract abi json to use.
    • SMART_WALLET_FACTORY_ADDRESS: the deployed smart wallet factory contract address.
    • RSK_ACCOUNT_ADDRESS: the rsk address that will own the smart wallet.
    • SMART_WALLET_RECOVERER: the rsk address that will be the recoverer account, in case the owner account is lost.
    • SMART_WALLET_INDEX: a wallet index, since we can have more than just one smart wallet per RSK address you can specify the index of the wallet.

2 (Optional). Now if you want, you can prefund this new address that will represent your smart wallet. To do that you can go to any wallet and send some tokens to that address. Also you can use web3 if you are working on regtest, here an example:

      import Web3 from "web3";

      const web3 = new Web3(<RSK_NODE_ENDPOINT>);

      const token = await new this.web3.eth.Contract(
        <ERC20_TOKEN_ABI>,
        <TOKEN_ADDRESS>
      );
     const accounts = await this.web3.eth.getAccounts();
     await token.methods.transfer(<SMART_WALLET_ADDRESS>, this.web3.utils.toWei(<AMOUNT_OF_TOKENS>, "ether"))
          .send({ from: accounts[0] });

Where variables are:

  • RSK_NODE_ENDPOINT: the RSK node endpoint where is running (ex: http://localhost:4444).
  • ERC20_TOKEN_ABI: the ERC20 token contract abi to use.
  • TOKEN_ADDRESS: the token contract address.
  • SMART_WALLET_ADDRESS: the generated address of last step.
  • AMOUNT_OF_TOKENS: string containing the amount of tokens in decimal unit.

NOTE: in this example we asume that the account[0] of regtest has tokens to use.

  1. Finally you need to deploy your smart wallet, to do so you must follow these steps:

    1. Use the provider from enveloping to that you have an example here:
      
      import { RelayProvider, resolveConfiguration } from "@rsksmart/enveloping";
      import Web3 from "web3";
      
      const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
      
      const web3 = new Web3(<RSK_NODE_ENDPOINT>);
      
      const config = await resolveConfiguration(web3.currentProvider,
      {
        verbose: window.location.href.includes("verbose"),
        onlyPreferredRelays: true,
        preferredRelays: ["http://localhost:8090"],
        factory: <SMART_WALLET_FACTORY_CONTRACT_ADDRESS>,
        gasPriceFactorPercent: 0,
        relayLookupWindowBlocks: 1e5,
        chainId: 33,
        relayVerifierAddress: <RELAY_VERIFIER_CONTRACT_ADDRESS>,
        deployVerifierAddress: <DEPLOY_VERIFIER_CONTRACT_ADDRESS>,
        smartWalletFactoryAddress: <SMART_WALLET_FACTORY_CONTRACT_ADDRESS>
      });
      resolvedConfig.relayHubAddress = <RELAY_HUB_CONTRACT_ADDRESS>;
      
      const provider = new RelayProvider(web3.currentProvider, config);
      
      provider.addAccount({
         address: <RSK_ACCOUNT_ADDRESS>,
         privateKey: Buffer.from(<RSK_ACCOUNT_PRIVATE_KEY>.replaceAll("0x", ""), "hex")
      });
      
      web3.setProvider(provider);
      
      const transaction = await provider.deploySmartWallet({
        from: <RSK_ACCOUNT_ADDRESS>,
        to: ZERO_ADDRESS,
        gas: "0x27100",
        value: "0",
        callVerifier: <DEPLOY_VERIFIER_CONTRACT_ADDRESS>,
        callForwarder: <SMART_WALLET_FACTORY_CONTRACT_ADDRESS>,
        tokenContract: <TOKEN_ADDRESS>,
        tokenAmount: <TOKEN_AMOUNT>,
        data: "0x",
        index: <SMART_WALLET_INDEX>,
        recoverer: <SMART_WALLET_RECOVERER>,
        isSmartWalletDeploy: true,
        onlyPreferredRelays: true,
        smartWalletAddress: <SMART_WALLET_ADDRESS>,
      });
      

    Where variables are:

    • RSK_NODE_ENDPOINT: the RSK node enpoint where is running (ex: http://localhost:4444).
    • SMART_WALLET_FACTORY_CONTRACT_ADDRESS: the deployed smart wallet factory contract address.
    • RELAY_VERIFIER_CONTRACT_ADDRESS: the deployed relay verifier contract address.
    • DEPLOY_VERIFIER_CONTRACT_ADDRESS: the deployed deploy verifier contract address.
    • RELAY_HUB_CONTRACT_ADDRESS: the deployed relay hub contract address.
    • RSK_ACCOUNT_ADDRESS: the RSK account address.
    • RSK_ACCOUNT_PRIVATE_KEY: the RSK account private key string.
    • TOKEN_ADDRESS: the token address.
    • TOKEN_AMOUNT: string containing the amount of tokens in decimal unit. This amount should be lower or equal to the amount of tokens that you transferred to the smart wallet account. If you didn’t, just set 0 here.
    • SMART_WALLET_INDEX: a wallet index, since we can have more than just one smart wallet per RSK address
    • SMART_WALLET_RECOVERER: the rsk address that will be the recoverer account, in case the owner account is lost.
    • SMART_WALLET_ADDRESS: the address generated on the first step.

After following all these steps you should be able to have a deployed smart wallet with tokens ready to be used.