Loading proofofbrain-blog...

Smart Contract Wallet v0.1 for Koinos

Now we have multisignatures wallets in Koinos! I'm glad to announce that I finished the first version of a Smart Contract Wallet. The code is open source and it is ready to use.

In summary, users will be able to use different private keys to manage their assets in Koinos (tokens, nfts, games, social apps, etc) by having all these assets in a single address. And apart of that they will have a option to set a recovery method in case of theft or loss of keys.

Authorities with multisignatures

Let's say you create the "transfer" authority. It looks like this:

{
  "name": "transfer",
  "authority": {
    "keyAuths": [
      {
        "address": "1DN7vxfg6srzCf69KVawp7D2mURgifLHsy",
        "weight": 1
      },
      {
        "address": "1Gvqdo9if6v6tFomEuTuMWP1D7H7U9yksb",
        "weight": 1
      },
      {
        "address": "16MT1VQFgsVxEfJrSGinrA5buiqBsN5ViJ",
        "weight": 1
      }
    ],
    "weightThreshold": 2,
    "lastUpdate": "1651445706384"
  }
}

The weight threshold is 2, and each address has weight 1. This means that this authority is valid if there is at least 2 of 3 signatures. When you associate this authority to the transfer function of the Koin Contract the next time you submit a transaction to make a transfer you will have to provide 2 signatures. This is a powerful feature for companies or associations in order to protect their assets.

Authorities defined with contracts

This type of authorities does not require signatures in the transactions but requires to be called by a specific contract. It looks like this:

{
  "name": "example",
  "authority": {
    "keyAuths": [
      {
        "contractId": "1DN7vxfg6srzCf69KVawp7D2mURgifLHsy",
        "weight": 1
      }
    ],
    "weightThreshold": 1,
    "lastUpdate": "1651445706384"
  }
}

This means that this authority is valid only if this call comes from the contract 1DN7vxfg6srzCf69KVawp7D2mURgifLHsy, that is, if this contract is the caller of the authorize function.

You can also combine this feature with multisignatures in order to add different options in the way you authorize some type of operation.

Owner authority

The owner authority is the most important authority in the wallet. It is the owner of the wallet. This authority is used to configure everything in the wallet (add authorities, update, protect contracts, etc).

Recovery authority

This is one of the greatest feature in this contract. This recovery is defined in the same way like the other authorities or the owner, but has the powerful characteristic of updating the owner! so it can be used in case of theft or loss of keys.

Let's say you define the recovery as 4 of 7 signatures from your friends. If for some reason you lose your private keys you could request to them to sign a transaction that updates the owner so you can recover the control of your wallet. Easy!

What happens if it is a key theft? What happens if the thief has the owner's private key? First of all, the owner can not update the recovery authority immediately, he has to wait 30 days in order to do so. By contrary, the recovery authority can update the owner without any delay. Then the user has this period of time to contact his friends in order to set a different owner and take the control back.

Recovery defined in a contract

The multisignature is not the unique way of defining a recovery method. As we saw above we can define contracts that can manage these authorities. Meaning that you could create a more complex set of instructions for the recovery in an external contract and then link it to your contract wallet.

A perfect use case for this is the recovery method proposed by Vitalik where only you know who are the friends that can trigger the recovery because you submit a hash of the list of addresses, not the list. So you only reveal the list to the public when you need to recover your account.

Multiple recovery methods

You can add multiple recovery methods. Let's see one example:

{
  "name": "recovery",
  "authority": {
    "keyAuths": [
      {
        "address": "1DN7vxfg6srzCf69KVawp7D2mURgifLHsy",
        "weight": 1
      },
      {
        "address": "1Gvqdo9if6v6tFomEuTuMWP1D7H7U9yksb",
        "weight": 1
      },
      {
        "address": "1BqtgWBcqm9cSZ97avLGZGJdgso7wx6pCA",
        "weight": 1
      },
      {
        "contractId": "16MT1VQFgsVxEfJrSGinrA5buiqBsN5ViJ",
        "weight": 2
      }
    ],
    "weightThreshold": 2,
    "lastUpdate": "1651445706384"
  }
}

In this example, there are 2 recovery methods:

  1. recovery using 2 of 3 signatures
  2. recovery defined in a external contract

Protections

The protections is the list of contracts that are protected using authorities. It's the link between authorities and contracts. Let's see one example:

{
  "protectedContract": {
    "contractId": "19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ",
    "entryPoint": 670398154
  },
  "authority": {
    "native": "koin-transfer",
    "lastUpdate": "1651509089669"
  }
}

In this example we are defining that when the koin contract (19JntSm8pSNETT9aHTwAUHC5RMoaSmgZPJ) is called to make a transfer (entry point 670398154) from our wallet, then we will authorize this transfer only if the transaction comply with the "koin-transfer" authority.

Protections defined in external contracts

You can create a more detailed protection in an external contract. I already created a contract example to have a daily limit of transfers.

Let's come back to the example of the thief. If he has my keys, how can I stop my money from being stolen? you could set a daily limit of transfers, meaning that you will lose some money but not everything (depending on the daily limit) until you recover your account. Isn't it wonderful?

Prevent upgrades as much as possible

As you probably noticed, my idea with this wallet contract is to give flexibility as much as possible, in particular by adding the option to connect external contracts that define custom logics. So you don't have to make contract upgrades in your main contract.

I do this because we have to be very very careful with the contract upgrades. The koinos blockchain gives a lot of power to the developers, and this means a lot of responsibility. If contract upgrades are not well managed this could result in the loss of the tokens forever.

So, in order to avoid this type of issues (specially for non devs), this contract works as plug&play. You can safely extend its functionality by adding external contracts. If for some reason the external contract is broken, you just remove it from the main contract and set a new one. The main contract will still working.

Thanks for your support

Check out the contract here https://github.com/joticajulian/koinos-as-sdk-examples/blob/main/wallet/assembly/Wallet.ts if you see critical bugs please let me know. The idea is to have a complete and robust solution for the whole community.

I also created a set of tests to make sure all the functions are working as expected.

If you like this contribution please consider your support on github sponsors https://github.com/sponsors/joticajulian or in the address 0x7F884D5985AE0720d830268B36D9CBDd7dbe8dcB (ethereum).

H2
H3
H4
3 columns
2 columns
1 column
2 Comments