A multi-signature wallet (multi-sig wallet) is a smart contract that requires multiple signatures to authorize transactions. This enhances security by ensuring that no single party can control the funds. Below is a detailed guide on how to create a multi-signature wallet in Solidity.
1. Setting Up the Contract
To create a multi-signature wallet, we need to define the contract structure, including state variables, events, and functions.
2. Sample Code
pragma solidity ^0.8.0;
contract MultiSigWallet {
address[] public owners;
mapping(address => bool) public isOwner;
uint public requiredSignatures;
struct Transaction {
address to;
uint value;
bool executed;
uint confirmations;
mapping(address => bool) isConfirmed;
}
Transaction[] public transactions;
event Deposit(address indexed sender, uint amount);
event TransactionCreated(uint indexed transactionId, address indexed to, uint value);
event TransactionExecuted(uint indexed transactionId);
modifier onlyOwner() {
require(isOwner[msg.sender], "Not an owner");
_;
}
constructor(address[] memory _owners, uint _requiredSignatures) {
require(_owners.length > 0, "Owners required");
require(_requiredSignatures > 0 && _requiredSignatures <= _owners.length, "Invalid number of required signatures");
for (uint i = 0; i < _owners.length; i++) {
address owner = _owners[i];
require(owner != address(0), "Invalid owner");
require(!isOwner[owner], "Owner not unique");
isOwner[owner] = true;
owners.push(owner);
}
requiredSignatures = _requiredSignatures;
}
receive() external payable {
emit Deposit(msg.sender, msg.value);
}
function createTransaction(address _to, uint _value) public onlyOwner {
uint transactionId = transactions.length;
transactions.push(Transaction({
to: _to,
value: _value,
executed: false,
confirmations: 0
}));
emit TransactionCreated(transactionId, _to, _value);
}
function confirmTransaction(uint _transactionId) public onlyOwner {
Transaction storage transaction = transactions[_transactionId];
require(!transaction.isConfirmed[msg.sender], "Transaction already confirmed");
transaction.isConfirmed[msg.sender] = true;
transaction.confirmations++;
}
function executeTransaction(uint _transactionId) public onlyOwner {
Transaction storage transaction = transactions[_transactionId];
require(transaction.confirmations >= requiredSignatures, "Not enough confirmations");
require(!transaction.executed, "Transaction already executed");
transaction.executed = true;
(bool success, ) = transaction.to.call{value: transaction.value}("");
require(success, "Transaction failed");
emit TransactionExecuted(_transactionId);
}
}
3. Explanation of the Code
- State Variables: The contract maintains a list of owners, a mapping to check if an address is an owner, and the number of required signatures.
- Transaction Struct: This struct holds details about each transaction, including the recipient address, value, execution status, and confirmations.
- Events: Events are emitted for deposits, transaction creation, and execution to log important actions.
- Modifiers: The
onlyOwner
modifier restricts access to certain functions to only the owners of the wallet. - Constructor: Initializes the contract with the owners and the required number of signatures.
- receive() function: This function allows the contract to accept Ether and emits a deposit event.
- createTransaction: This function allows owners to create a new transaction, which is stored in the transactions array.
- confirmTransaction: Owners can confirm a transaction, increasing the confirmation count.
- executeTransaction: Once the required number of confirmations is reached, this function executes the transaction by transferring the specified value to the recipient address.
4. Conclusion
Creating a multi-signature wallet in Solidity enhances the security of fund management by requiring multiple approvals for transactions. This contract structure is essential for organizations or groups that want to ensure collective control over their assets. Understanding how to implement and manage a multi-signature wallet is crucial for developers working in the blockchain space.