This is a smart contract that acts as an off-chain signature-based shared wallet amongst different signers that showcases use of meta-transaction knowledge and ECDSA recover()
. If you are looking for the challenge, go to the challenges repo within scaffold-eth!
If you are unfamiliar with these concepts, check out all the ETH.BUILD videos by Austin Griffith, especially the Meta Transactions one!
At a high-level, the contract core functions are carried out as follows:
Off-chain: ⛓🙅🏻♂️ - Generation of a packed hash (bytes32) for a function call with specific parameters through a public view function . - It is signed by one of the signers associated to the multisig, and added to an array of signatures (bytes[] memory signatures
)
On-Chain: ⛓🙆🏻♂️
bytes[] memory signatures
is then passed intoexecuteTransaction
as well as the necessary info to userecover()
to obtain the public address that ought to line up with one of the signers of the wallet.- This method, plus some conditional logic to avoid any duplicate entries from a single signer, is how votes for a specific transaction (hashed tx) are assessed.
- If it's a success, the tx is passed to the
call(){}
function of the deployed MetaMultiSigWallet contract (this contract), thereby passing theonlySelf
modifier for any possible calls to internal txs such as (addSigner()
,removeSigner()
,transferFunds()
,updateSignaturesRequried()
).
Cool Stuff that is Showcased: 😎
- NOTE: Showcases how the
call(){}
function is an external call that ought to increase the nonce of an external contract, as they increment differently from user accounts. - Normal internal functions, such as changing the signers, and adding or removing signers, are treated as external function calls when
call()
is used with the respective transaction hash. - Showcases use of an array (see constructor) populating a mapping to store pertinent information within the deployed smart contract storage location within the EVM in a more efficient manner.
required: Node plus Yarn and Git
git clone https://github.com/scaffold-eth/scaffold-eth-challenges challenge-5-multisig
cd challenge-5-multisig
git checkout challenge-5-multisig
yarn install
yarn chain
in a second terminal window:
cd challenge-5-multisig
yarn start
🔏 Edit your smart contract MultiSigWallet.sol
in packages/hardhat/contracts
📝 Edit your frontend App.jsx
in packages/react-app/src
💼 Edit your deployment script deploy.js
in packages/hardhat/scripts
📱 Open http://localhost:3000 to see the app
in a third terminal window:
yarn backend
🔧 Configure your deployment in packages/hardhat/scripts/deploy.js
Edit the chainid, your owner addresses, and the number of signatures required:
in a fourth terminal deploy with your frontend address as one of the owners:
yarn deploy
Use the faucet wallet to send your multi-sig contract some funds:
To add new owners, use the "Owners" tab:
This will take you to a populated transaction create page:
Create & sign the new transaction:
You will see the new transaction in the pool (this is all off-chain):
Click on the ellipsses button [...] to read the details of the transaction
Give your account some gas at the faucet and execute the transaction
The transction will appear as "executed" on the front page:
Create a transaction to send some funds to your frontend account:
This time we will need a second signature:
(You'll notice you don't need ⛽️gas to sign transactions.)
Execute the transction to transfer the funds:
(You might need to trigger a new block by sending yourself some faucet funds or something. HartHat blocks only get mined when there is a transaction.)
💼 Edit your deployment script deploy.js
in packages/hardhat/scripts
🔏 Edit your contracts form, MetaMultiSigWallet.sol
in packages/hardhat/contracts
📝 Edit your frontend in packages/react-app/src/views
You may not want every signer to create new transfers, only allow them to sign existing transactions or a mega-admin role who will be able to veto any transaction.
Make a MultiSig wallet to store your precious doodle-NFTs!?
🛰 Ready to deploy to a testnet?
Change the
defaultNetwork
inpackages/hardhat/hardhat.config.js
🔐 Generate a deploy account with yarn generate
👛 View your deployer address using yarn account
(You'll need to fund this account. Hint: use an instant wallet to fund your account via QR code)
👨🎤 Deploy your wallet:
yarn deploy
✏️ Edit your frontend
App.jsx
inpackages/react-app/src
to change thetargetNetwork
to wherever you deployed your contract:
You should see the correct network in the frontend:
Also change the poolServerUrl constant to your deployed backend (via yarn backend)
Alternatively you can use the pool server url in the above screenshot
You will need to get a key from infura.io and paste it into
constants.js
inpackages/react-app/src
:
⚙️ build and upload your frontend and share the url with your friends...
# build it:
yarn build
# upload it:
yarn surge
OR
yarn s3
OR
yarn ipfs
👩❤️👨 Share your public url with friends, add signers and send some tasty ETH to a few lucky ones 😉!!
(Written by: @umphams)
Join the telegram support chat 💬 to ask questions and find others building with 🏗 scaffold-eth!
🙏 Please check out our Gitcoin grant too!