# Using on-chain multisigs on Cosmos SDK
## Intro
In this article we'll go over the creation of a multisig wallet, and how to perform some actions with it.
## Setup
We'll create a multisig with 3 members with a 2/3 passing threshold.
First create the 3 members, Alice, Bob and Carol:
```bash!
simd keys add alice --keyring-backend test --home ./.testnets/node0/simd/
simd keys add bob --keyring-backend test --home ./.testnets/node0/simd/
simd keys add carol --keyring-backend test --home ./.testnets/node0/simd/
```
And we initialize them with some tokens (sent from one of our nodes):
```bash!
simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) $(simd keys show alice --address --keyring-backend=test --home ./.testnets/node0/simd/) 100stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/
simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) $(simd keys show bob --address --keyring-backend=test --home ./.testnets/node0/simd/) 100stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/
simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) $(simd keys show carol --address --keyring-backend=test --home ./.testnets/node0/simd/) 100stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/
```
Now we craft our initialization message, in it we'll include the members' addresses, their weights and the configuration of our multisig.
```json
{
"members": [
{
"address": "cosmos1pr26h2vq9adq3acvh37pz6wtk65u3y8798scq0",
"weight": 1000
},
{
"address": "cosmos1j4p2xlg393rg4mma0058alzgvkrjdddd2f5fll",
"weight": 1000
},
{
"address": "cosmos1vaqh39cdex9sgr46ef0tdln5cn0hdyd3s0lx4l",
"weight": 1000
}
],
"config": {
"threshold": 2000,
"quorum": 2000,
"voting_period": 86400,
"revote": false,
"early_execution": true
}
}
```
In the configuration we set the threshold and quorum to the same, 2/3 of the members must vote yes to pass the proposal. Other configurations can set the quorum and threshold to different values to mimic how organizations work.
We've also set `early_execution` to true, to allow executing as soon as the proposal passes.
Voting period is in seconds, so we've set that to 24h. And finally `revote` was set to false, because we don't want to allow members to change their vote mid-way through.
To initialize the multisig, we have to run the `accounts init` passing the account type and the json we created.
```bash!
initcontents=$(cat init.json)
simd tx accounts init multisig $initcontents --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from alice
```
If everything goes well, we'll get back a tx hash, and we'll check the tx result to get our newly created multisig's address.
```bash!
simd q tx 472B5B4E181D2F399C0ACE4DEEB26FE4351D13E593ED8E793B005C48BFD32621 --output json | jq -r '.events[] | select(.type == "account_creation") | .attributes[] | select(.key == "address") | .value'
```
In this case, the address is `cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu`. We can now send tokens to it, just like to a normal account.
```bash!
simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu 10000stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/
```
## Proposals
### Create proposal
In this multisig, every action is a proposal. We'll do a simple proposal to send tokens from the multisig to Alice.
```json
{
"proposal": {
"title": "Send 1000 tokens to Alice",
"summary": "Alice is a great multisig member so let's pay her.",
"messages": [
{
"@type": "/cosmos.bank.v1beta1.MsgSend",
"from_address": "cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu",
"to_address": "cosmos1pr26h2vq9adq3acvh37pz6wtk65u3y8798scq0",
"amount": [
{
"denom": "stake",
"amount": "1000"
}
]
}
]
}
}
```
> The content of messages was created using a simple `tx send` command and passing the flag `--generate-only` so we could copy the message.
Now we send the tx that will create the proposal:
```bash!
propcontents=$(cat createprop.json)
simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgCreateProposal $propcontents --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from alice
```
This will again return a tx hash that we can use to find out the newly created proposal.
```bash!
simd q tx 5CA4420B67FB040B3DF2484CB875E030123662F43AE9958A9F8028C1281C8654 --output json | jq -r '.events[] | select(.type == "proposal_created") | .attributes[] | select(.key == "proposal_id") | .value'
```
In this case, because this is the first proposal, we'll get that the proposal ID is 0. We can use this to query it.
```bash!
simd q accounts query cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.QueryProposal '{"proposal_id":1}'
```
We get back all the details from the proposal, including the end of the voting period and the current status of the proposal.
```yaml
response:
'@type': /cosmos.accounts.defaults.multisig.v1.QueryProposalResponse
proposal:
messages:
- '@type': /cosmos.bank.v1beta1.MsgSend
amount:
- amount: "1000"
denom: stake
from_address: cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu
to_address: cosmos1pr26h2vq9adq3acvh37pz6wtk65u3y8798scq0
status: PROPOSAL_STATUS_VOTING_PERIOD
summary: Alice is a great multisig member so let's pay her.
title: Send 1000 tokens to Alice
voting_period_end: "1717064354"
```
### Vote on the proposal
Just like before, we'll use `tx accounts execute`, but this time to vote. As we have a 2/3 passing threshold, we have to vote with at least 2 members.
```bash!
simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgVote '{"proposal_id":0, "vote":"VOTE_OPTION_YES"}' --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from alice --yes
simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgVote '{"proposal_id":0, "vote":"VOTE_OPTION_YES"}' --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from bob --yes
```
### Execute the proposal
Once we got enough votes, we can execute the proposal.
```bash!
simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgExecuteProposal '{"proposal_id":0}' --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from bob --yes
```
Querying the tx hash will get us information about the success or failure of the proposal execution.
```yaml
- attributes:
- index: true
key: proposal_id
value: "0"
- index: true
key: yes_votes
value: "2000"
- index: true
key: no_votes
value: "0"
- index: true
key: abstain_votes
value: "0"
- index: true
key: status
value: PROPOSAL_STATUS_PASSED
- index: true
key: reject_err
value: <nil>
- index: true
key: exec_err
value: <nil>
- index: true
key: msg_index
value: "0"
type: proposal_tally
```
Now checking the multisig and Alice's balance, we'll see that the send was performed correctly.
```bash!
simd q bank balances cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu
balances:
- amount: "9000"
denom: stake
pagination:
total: "1"
```
```bash!
simd q bank balances $(./build/simd keys show alice --address)
balances:
- amount: "1080"
denom: stake
pagination:
total: "1"
```