Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
[
]
Welcome, blockchain enthusiasts and security-conscious developers! Today, we’re diving into an exciting smart contract that brings multi-signature functionality to the BitTorrent Chain (BTTC) — the MultiSigWallet contract. This powerful piece of code enhances transaction security by requiring multiple approvals before execution. Let’s unpack this digital fortress and see how it works!
Imagine a digital vault that requires multiple keys to open, ensuring that no single person can access the funds alone. That’s exactly what our MultiSigWallet contract achieves. It’s a robust system for managing shared funds with enhanced security and consensus.
Let’s break down the key components of our contract:
address[] public owners;
uint public numConfirm;struct Transaction {
address to;
uint value;
bool executed;
}
mapping(uint => mapping(address => bool)) isConfirmed;
mapping(address => bool) isOwner;
Transaction[] public transactions;
These variables and structs form the backbone of our contract: — owners: An array of addresses that have ownership rights. — numConfirm: The number of confirmations required to execute a transaction. — Transaction: A struct defining the structure of each transaction. — isConfirmed: A nested mapping to track confirmations for each transaction. — isOwner: A mapping to quickly check if an address is an owner. — transactions: An array storing all submitted transactions.
Events are crucial for transparency and off-chain tracking:
event TransactionSubmitted(
uint transactionId,
address sender,
address receiver,
uint amount
);
event TransactionConfirmed(uint transactionId);
event TransactionExecuted(uint transactionId);
These events help in tracking the lifecycle of transactions:
– TransactionSubmitted: Fired when a new transaction is proposed.
– TransactionConfirmed: Emitted when an owner confirms a transaction.
– TransactionExecuted: Logs when a transaction is successfully executed.
The constructor initializes the wallet with the specified owners and confirmation threshold:
constructor(address[] memory _owners, uint _numConfirmationRequired) {
require(_owners.length > 1, "owners required must grater than 1");
require(
_numConfirmationRequired > 0 &&
_numConfirmationRequired <= _owners.length,
"Num of confirmation is not sync with num of owner"
);
numConfirm = _numConfirmationRequired;for (uint i = 0; i < _owners.length; i++) {
require(_owners[i] != address(0), "Invalid Owner");
owners.push(_owners[i]);
isOwner[_owners[i]] = true;
}
}
This constructor ensures that: — There are at least two owners. — The number of required confirmations is valid. — All provided owner addresses are valid.
function submitTransaction(address _to) public payable {
require(_to != address(0), "Invalid address");
require(msg.value > 0, "Transfer amount must be grater than 0 ");
uint transactionId = transactions.length;transactions.push(
Transaction({to: _to, value: msg.value, executed: false})
);
emit TransactionSubmitted(transactionId, msg.sender, _to, msg.value);
}
This function allows anyone to propose a new transaction, creating a new Transaction struct and emitting a TransactionSubmitted event.
function confirmTransaction(uint _transactionId) public onlyOwner {
require(_transactionId < transactions.length, "Invalid transaction");
require(
!isConfirmed[_transactionId][msg.sender],
"Transaction is already confirm by owner"
);
isConfirmed[_transactionId][msg.sender] = true;
emit TransactionConfirmed(_transactionId);if (isTransactionConfirmed(_transactionId)) {
executeTransaction(_transactionId);
}
}
Only owners can confirm transactions. This function checks if the transaction is valid and not already confirmed by the caller. If the required number of confirmations is reached, it automatically triggers execution.
function isTransactionConfirmed(
uint _transactionId
) public view returns (bool) {
require(_transactionId < transactions.length, "Invalid transaction");
uint confirmation;
for (uint i = 0; i < numConfirm; i++) {
if (isConfirmed[_transactionId][owners[i]]) {
confirmation++;
}
}
return confirmation >= numConfirm;
}
This view function checks if a transaction has received the required number of confirmations.
function executeTransaction(uint _transactionId) public payable {
require(_transactionId < transactions.length, "Invalid transaction");
require(
!transactions[_transactionId].executed,
"Transaction is already executed"
);(bool success, ) = transactions[_transactionId].to.call{
value: transactions[_transactionId].value
}("");
require(success, "Transaction Execution Failed ");
transactions[_transactionId].executed = true;
emit TransactionExecuted(_transactionId);
}
This function executes a confirmed transaction, transferring the funds to the specified recipient and marking the transaction as executed.
This MultiSigWallet contract opens up a world of possibilities:
The MultiSigWallet smart contract is more than just code — it’s a paradigm shift in how we think about digital asset security and management. By requiring multiple signatures for transactions, we’re creating a more robust, trustworthy system for handling funds on the blockchain.
As you explore the potential of this contract on BTTC, remember: you’re not just using a wallet, you’re pioneering a new era of collaborative and secure digital finance.
So, who will you trust with your digital keys? The blockchain is waiting, and multi-signature security is ready to protect your assets!
Github URL:
https://github.com/adeelch9/bttc-examples/tree/master/projects/multisig
[