# Simple multisig contract with Fift (https://docs-dmpho5eos-ton-core-docs.vercel.app/llms/languages/fift/multisig/content.md)



<Callout type="note">
  The official smart contract language of TON Blockchain is [Tolk](/llms/tolk/overview/content.md). Fift is now a **legacy** language, with its compiler no longer maintained.
</Callout>

This information is **very low-level**. It could be hard for newcomers and designed for advanced people who want to understand [Fift](/llms/languages/fift/content.md). The use of Fift is not required in everyday tasks.

## Overview [#overview]

This tutorial helps you learn how to deploy your multisig contract. Recall that a $(n, k)$-multisig contract is a multi-signature wallet with $n$ private key holders, which accepts requests to send messages if the request (a.k.a. order, query) collects at least $k$ holders' signatures.

Based on the original multisig contract code and updates by akifoq:

* [Original TON Blockchain multisig-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/multisig-code.fc)
* [akifoq/multisig](https://github.com/akifoq/multisig) with Fift libraries to work with multisig.

<Callout type="tip" title="Prefer videos over text?">
  Watch this if you are new to multi-signature wallets: [What is Multisig Technology? (video)](https://www.youtube.com/watch?v=yeLqe_gg2u0)
</Callout>

## What you'll learn [#what-youll-learn]

* How to create and customize a simple multisig wallet.
* How to deploy a multisig wallet using a Lite client.
* How to sign a request and send it in a message to the blockchain.

## Set up your environment [#set-up-your-environment]

Before we begin our journey, check and prepare your environment.

* Install `func`, `fift`, `lite-client` binaries, and `fiftlib` from the [latest GitHub release](https://github.com/ton-blockchain/ton/releases/latest).
* Clone the [repository](https://github.com/akifoq/multisig) and open its directory in CLI.

```shell
git clone https://github.com/akifoq/multisig.git
cd ./multisig
```

## Get started [#get-started]

1. Compile the code to Fift.
2. Prepare multisig owner's keys.
3. Deploy your contract.
4. Interact with the deployed multisig wallet in the blockchain.

### Compile the contract [#compile-the-contract]

Compile the contract to Fift with:

```shell
func -o multisig-code.fif -SPA stdlib.fc multisig-code.fc
```

### Prepare multisig owner's keys [#prepare-multisig-owners-keys]

#### Create participant's keys [#create-participants-keys]

To create a key, you need to run:

```shell
fift -s new-key.fif $KEY_NAME$
```

* Where `KEY_NAME` is the file name where the private key will be written.

For example:

```shell
fift -s new-key.fif multisig_key
```

We'll receive a `multisig_key.pk` file with the private key inside.

#### Collect public keys [#collect-public-keys]

Also, the script will issue a public key in the format:

```
Public key = Pub5XqPLwPgP8rtryoUDg2sadfuGjkT4DLRaVeIr08lb8CB5HW
```

Anything after `Public key = ` needs to be saved somewhere!

Let's store it in a file called `keys.txt`. It's essential to have one public key per line.

### Deploy your contract [#deploy-your-contract]

#### Deploy via `lite-client` [#deploy-via-lite-client]

After creating all the keys, you need to collect the public keys into a text file, `keys.txt`.

For example:

```shell
PubExXl3MdwPVuffxRXkhKN1avcGYrm6QgJfsqdf4dUc0an7/IA
PubH821csswh8R1uO9rLYyP1laCpYWxhNkx+epOkqwdWXgzY4
```

After that, you need to run:

```shell
fift -s new-multisig.fif 0 $WALLET_ID$ wallet $KEYS_COUNT$ ./keys.txt
```

* `$WALLET_ID$`: the wallet number assigned to the current key. It is recommended that each new wallet with the same key use a unique `$WALLET_ID$`.
* `$KEYS_COUNT$`: the number of keys needed for confirmation, usually equal to the number of public keys.

<Callout title="Wallet ID explained">
  It is possible to create many wallets with the same keys (Alice's key, Bob's key). What should we do if Alice and Bob already share a wallet? That's why `$WALLET_ID$` is crucial here.
</Callout>

The script will output something like:

```shell
new wallet address = 0:4bbb2660097db5c72dd5e9086115010f0f8c8501e0b8fef1fe318d9de5d0e501

(Saving address to file wallet.addr)

Non-bounceable address (for init): 0QBLuyZgCX21xy3V6QhhFQEPD4yFAeC4_vH-MY2d5dDlAbel

Bounceable address (for later access): kQBLuyZgCX21xy3V6QhhFQEPD4yFAeC4_vH-MY2d5dDlAepg

(Saved wallet creating query to file wallet-create.boc)
```

Keep the bounceable address — this is the wallet address we will be using.

<Callout>
  If you have a "public key must be 48 characters long" error, please make sure your `keys.txt` uses Unix-style line endings (LF). For example, line endings can be changed via Sublime Text.
</Callout>

#### Activate your contract [#activate-your-contract]

You need to send some TON to the newly generated wallet. For example, 0.5 TON. You can send testnet coins via [`@testgiver_ton_bot`](https://t.me/testgiver_ton_bot).

After that, run `lite-client`:

```shell
lite-client -C global.config.json
```

<Callout title="Where to get global.config.json?">
  You can get a fresh config file `global.config.json` for [Mainnet](https://ton.org/global-config.json) or [Testnet](https://ton.org/testnet-global.config.json).
</Callout>

After starting a Lite client, it's best to run the `time` command in the `lite-client` console to make sure the connection was successful:

```shell
time
```

Okay, Lite client works!

After that, you need to deploy the wallet. Run the command:

```shell
sendfile ./wallet-create.boc
```

After that, the wallet will be ready to work within a minute.

### Interact with a multisig wallet [#interact-with-a-multisig-wallet]

#### Create a request [#create-a-request]

First, you need to create a message request:

```shell
fift -s create-msg.fif $ADDRESS$ $AMOUNT$ $MESSAGE$
```

* `$ADDRESS$` - address where to send coins.
* `$AMOUNT$` - number of coins (in TON).
* `$MESSAGE$` - the file name for the compiled message.

For example:

```shell
fift -s create-msg.fif EQApAj3rEnJJSxEjEHVKrH3QZgto_MQMOmk8l72azaXlY1zB 0.1 message
```

<Callout type="tip">
  Use the `-C comment` attribute to add a comment for your transaction. To get more information, run the `create-msg.fif` file without parameters.
</Callout>

#### Choose a wallet [#choose-a-wallet]

Next, you need to choose a wallet to send coins from:

```shell
fift -s create-order.fif $WALLET_ID$ $MESSAGE$ -t $AWAIT_TIME$
```

Where:

* `$WALLET_ID$` — ID of the wallet backed by this multisig contract.
* `$AWAIT_TIME$` — time in seconds the smart contract will await signatures from the multisig wallet owners for the request.
* `$MESSAGE$` — name of the message BoC file created in the previous step.

<Callout>
  The request expires if `$AWAIT_TIME$` elapses before the request is signed. As usual, `$AWAIT_TIME$` equals a couple of hours (7200 seconds).
</Callout>

For example:

```shell
fift -s create-order.fif 0 message -t 7200
```

The resulting file is saved as `order.boc`.

<Callout>
  `order.boc` must be shared with key holders; they must sign it.
</Callout>

#### Sign your part [#sign-your-part]

To sign, run:

```shell
fift -s add-signature.fif $KEY$ $KEY_INDEX$
```

* `$KEY$` - file name containing the private key to sign, without extension.
* `$KEY_INDEX$` - index of the given key in `keys.txt` (zero-based).

For example, for our `multisig_key.pk` file:

```shell
fift -s add-signature.fif multisig_key 0
```

#### Create a message [#create-a-message]

After everyone has signed the order, it needs to be turned into a message for the wallet and signed again with the following command:

```shell
fift -s create-external-message.fif wallet $KEY$ $KEY_INDEX$
```

In this case, only one signature from a wallet owner is enough. The idea is that you can't attack a contract with invalid signatures.

For example:

```shell
fift -s create-external-message.fif wallet multisig_key 0
```

#### Send the signed message to the TON blockchain [#send-the-signed-message-to-the-ton-blockchain]

After that, start `lite-client` again:

```shell
lite-client -C global.config.json
```

And finally, we want to send our sign! Just run:

```shell
sendfile wallet-query.boc
```

If everyone else signed the request, it would be completed!

You did it!

## See also [#see-also]

* [Multisignature wallet v2](https://github.com/ton-blockchain/multisig-contract-v2)
