Skip to content

A minimal multi sig wallet manager on Ethereum based on meta transactions (confirm with signature) written in Typescript. Mobile friendly. Shareable links.

License

Notifications You must be signed in to change notification settings

dvinubius/meta-multisig-typescript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

15 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ— Metatransaction MultiSig Manager

Create and manage multi sig contracts which execute metatransactions.

Users can create and manage their multi sig smart contracts.

Metatransactions allow for signatures to be given off-chain (no gas fees to pay except once, when all required signatures have been given)

MultiSigs management is based on a smart contract factory 🏭

Live on Rinkeby 🀩

meta-multisig

Use Case

It's for personal use / within groups of mutual trust (not a forwarder contract) It covers "usual: use casess for a regular multi sig contract, but additionally tx costs are kept minimal. As a user I can create a multi sig contract to hold funds for me. I can set up several signer accounts that can trigger my contract's functions. My contract's built-in functions include

  • basic transfer of funds
  • adding a trusted signer
  • removing a trusted signer

Metatransactions enable gasless blockchain interaction (kind of).

The regular Multi Sig

Several signers confirm a multisig transaction. This happens on-chain, so each signer performs a confirmation transaction.

Meta Transaction Multi Sig (this app)

Let the signers merely give their signature (off-chain). With all needed signatures collected, only 1 on-chain transaction is needed. The multisig contract verifies that enough valid signatures were given.

In this particular project we limited the functionality to 3 basic types of transaction:

  • transfer funds from multisig
  • add multisig signer
  • remove multisig signer By following the design pattern you should easily be able to extend the functionality.

If you're an absolute noob to web3, check out the Ethereum Speed Run.

@dev ⚠️ Production Bundle Issue + Workaround

We were surprised when the production bundle failed to work because of moralis throwing a TypeError: Right-hand side of 'instanceof' is not callable. The only solution we were able to find for this involves changing code in the react-moralis dependency.

  1. go to packages/vite-app-ts/node_modules/react-moralis/lib/index.esm.js
  2. change import MoralisImport from 'moralis'; to import MoralisImport from 'moralis/dist/moralis.js';

You may not encounter the issue above due to updates in the react-moralis package.

@dev Design Decisions

On-Chain

Signatures are always sorted on the frontend before a metatransaction is executed. This enables cheaper duplicate prevention. The more expensive solution (in terms of gas costs) would have been to do a duplicate check on-chain.

The older scaffold-eth meta multi sig implementation is not optimal in terms of the contract code.

In the present repo

  • we took out the streaming functionality for simplicity
  • we took out the nonces because there is no need for them (see below)
  • we execute metatransactions without any value attached; metatransactions with transferFunds(address, uint256) as calldata have everything encoded in the calldata and they require the multisig to have sufficient balance beforehand
  • metatransaction execution always makes the multisig contract perform a call to itself with the pertaining "inner" calldata

⛽️ Gas costs are reduced to a minimum. However, we keep an array of the owners on-chain (address[] public owners and all the updates that go with it). This storage allows for enumerating the owners of a multisig. It helps to provide better UX on the frontend. In some rare cases you may want to interact with a multisig contract directly, not via the web frontend and not relying on the Moralis backend. The owners array in EVM storage seems like a small price to pay, but in the end you could eliminate it, retrieve owners via Moralis and have an even more gas-efficient smart contract.

The hardhat console contract is wired up for dev purposes, you may want to remove it in production, especially if you deploy to Ethereum and you care about deployment costs.

πŸ“ Nonces

As a sidenote, nonces do make sense for metatransactions, but rather in a scenario where several non-trusting parties are involved.

More specifically, when there is a (supposedly) trusted 3rd party forwarder/executor that takes signed messages from users and executes them on their behalf, thereby paying the gas costs. Nonces prevent the forwarder from executing the same transaction multiple times.

Attempts have been made to standardize solutions for this kind of scenario via EIP-2771. See the work from OpenZeppelin here.

Moralis Backend

We use it to

  • store metaTransactions
  • index on-chain events (creating multisigs, changing owners of multisigs)

Storing metatransactions was the primary reason to use a backend, but since Moralis can easily index contract events, it's convenient to use for queries and it reduces the number of RPC requests.

The Moralis integration is optimized to scale: When user logs in with account X, the query for "My Vaults" runs on the backend via cloud code, returning the vaults where X is currently a co-owner.

  • This includes vaults that initially did not have X as a co-owner, but added X later.
  • This excludes vaults where X initially was a co-owner, but then was excluded.

⚠️ Frontend consistency. The frontend displays on-chain data correctly only as long as contract interactions go through this frontend. This should be fine for our use case.

Suboptimal solutions

At the time of dev Moralis wasn't reliably performing query subscription updates, therefore we had to also perform some vanilla web3 event listening. Also, Moralis wasn't reliably syncing events with indexed address array arguments (event Foo(address[] indexed bar)), so we had to avoid indexing address array event args.

If you want to develop on top of this repo, learn from the docs how to use Moralis. You need to:

  • setup a server
  • sync events from your MSFactory contract (when vaults are created and when owners changes happen)
  • configure access to Moralis DB tables (by default each table has public read/write/create_field access)

Frontend UX

The should be improved for production.

  • No pagination yet (necessary for executed transactions, they add up over time)
  • Suboptimal responsiveness: Not very comfortable below 450px width. But still mobile friendly to a large extent

eth-components

Instead of using the dependency eth-components (v3) we replicated those components locally in order to tweak some of them. We kept them in the dependencies though.

In order to use the eth-components package, change all imports like ... from '~~/eth-components/...' to ... from 'eth-components/...';

Features of the Scaffold Eth Contract Factory Setup

πŸ§ͺ Quickly experiment with Solidity using a frontend that adapts to your smart contract:

image

πŸš€ Start with a basic master-detail UI, customize it for your needs

πŒ‹ Debug your contracts with a simil master-detail UI

πŸ— Scaffold-Eth Typescript

This is based on the typescript repo of scaffold.eth. The directories that you'll use are:

packages/vite-app-ts/
packages/hardhat-ts/

πŸ„β€β™‚οΈ Building on scaffold-eth-typescript

Prerequisites: Node plus Yarn and Git

install your dependencies:

yarn install

in a second terminal window, start a hardhat node:

yarn chain

in a third terminal window, πŸ›° deploy your contract and start the app:

# build hardhat & external contracts types
yarn contracts:build 
# deploy your hardhat contracts
yarn deploy
# start vite 
yarn start 

🌍 You need an RPC key for production deployments/Apps, create an Alchemy account and replace the value of ALCHEMY_KEY = xxx in packages/react-app/src/constants.js

πŸ” Edit your smart contract YourContract.sol in packages/hardhat/contracts

πŸ“ Edit your frontend MainPage.tsx in packages/react-app/src

πŸ’Ό Edit your deployment scripts in packages/hardhat/deploy

πŸ“± Open http://localhost:3000 to see the app

Guides

  • Check out eth-hooks docs for example of how to use hooks
  • you can look at speedrun ethereum to get started with scaffold-eth-typescript and web3.
    • 🏁 Make sure to click on the typescript tab!

πŸ›  Buidl

Check out all the active branches, open issues, and join/fund the 🏰 BuidlGuidl!

Follow the full Ethereum Speed Run

πŸ’Œ P.S.

You need an RPC key for testnets and production deployments, create an Alchemy account and replace the value of ALCHEMY_KEY = xxx in packages/react-app/src/constants.js with your new key.

πŸ’¬ Support Chat

Join the telegram support chat πŸ’¬ to ask questions and find others building with πŸ— scaffold-eth!

πŸ™πŸ½ Support us!

Please check out our Gitcoin grant too!

About

A minimal multi sig wallet manager on Ethereum based on meta transactions (confirm with signature) written in Typescript. Mobile friendly. Shareable links.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published