Developers Forum for XinFin XDC Network

Cover image for [Informative] How to create Multi-Sig Wallet Contract with XDC Network!
Vinn
Vinn

Posted on • Updated on

[Informative] How to create Multi-Sig Wallet Contract with XDC Network!

The digital world of blockchain and cryptocurrency relies heavily on robust security measures to safeguard assets from unauthorized access and potential threats. As technology advances, so do the methods employed to fortify asset protection. Emerging as a promising solution is the Multi-Signature (Multi-Sig) wallet, a innovative approach to enhancing the security of digital assets. In this article, we will explore the intricacies of Multi-Sig wallets, examining their mechanics, advantages, and practical applications across various domains.

Image description

Understanding Multi-Signature Wallets:
Multi-Signature wallets, often referred to as Multi-Sig wallets, are a type of digital wallet that requires multiple private keys to authorize a transaction. Unlike traditional wallets that rely on a single private key for access and control, Multi-Sig wallets distribute control among multiple parties, adding an extra layer of security and accountability.

Real-World Applications:
Multi-Sig wallets find applications in various scenarios, including cryptocurrency exchanges, decentralized finance (DeFi) platforms, and corporate treasury management. They provide enhanced security, risk mitigation, and governance capabilities, making them ideal for managing high-value assets and sensitive transactions.

The MultiSigWallet Contract:
To grasp the mechanics of Multi-Sig wallets, let’s dissect a basic MultiSigWallet contract written in Solidity:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MultiSigWallet {
event Deposit(address indexed sender, uint amount);
event Submission(uint indexed txId);
event Confirmation(address indexed owner, uint indexed txId);
event Execution(uint indexed txId);
event ExecutionFailure(uint indexed txId);
address[] public owners;
mapping(address => bool) public isOwner;
uint public required;
struct Transaction {
address to;
uint value;
bytes data;
bool executed;
}
Transaction[] public transactions;
mapping(uint => mapping(address => bool)) public confirmations;
modifier onlyOwner() {
require(isOwner[msg.sender], "Not owner");
_;
}
modifier txExists(uint _txId) {
require(_txId < transactions.length, "Tx does not exist");
_;
}
modifier notExecuted(uint _txId) {
require(!transactions[_txId].executed, "Tx already executed");
_;
}
modifier notConfirmed(uint _txId) {
require(!confirmations[_txId][msg.sender], "Tx already confirmed");
_;
}
constructor(address[] memory _owners, uint _required) {
require(_owners.length > 0, "Owners required");
require(_required > 0 && _required <= _owners.length, "Invalid required number of owners");
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);
}
required = _required;
}
receive() external payable {
emit Deposit(msg.sender, msg.value);
}
function submitTransaction(address _to, uint _value, bytes memory _data)
public onlyOwner
{
uint txId = transactions.length;
transactions.push(Transaction({
to: _to,
value: _value,
data: _data,
executed: false
}));
emit Submission(txId);
}
function confirmTransaction(uint _txId)
public onlyOwner txExists(_txId) notConfirmed(_txId)
{
confirmations[_txId][msg.sender] = true;
emit Confirmation(msg.sender, _txId);
}
function executeTransaction(uint _txId)
public onlyOwner txExists(_txId) notExecuted(_txId)
{
if (isConfirmed(_txId)) {
Transaction storage txn = transactions[_txId];
(bool success,) = txn.to.call{value: txn.value}(txn.data);
if (success) {
txn.executed = true;
emit Execution(_txId);
} else {
emit ExecutionFailure(_txId);
}
}
}
function isConfirmed(uint _txId) public view returns (bool) {
uint count = 0;
for (uint i = 0; i < owners.length; i++) {
if (confirmations[_txId][owners[i]]) count += 1;
if (count == required) return true;
}
return false;
}
}
Enter fullscreen mode Exit fullscreen mode

The Contract Interaction Flow:
The interaction with a MultiSig wallet involves several steps, including depositing funds, submitting transactions, confirming transactions, and executing transactions. Each step requires the involvement of multiple owners to authorize and execute transactions securely.

To explain the contract interaction flow using Remix, we’ll go through the process step by step, from contract deployment with XDC Apothem Network to executing a transaction:

Setup the Environment

  • Open Remix IDE (https://remix.ethereum.org/).
  • Copy the MultiSigWallet contract code into a new file in Remix.
  • Compile the contract by selecting the appropriate compiler version (0.8.0 in this case) from the Remix Compiler tab.
  • XDCPay Wallet: Add the XDCPay extension to your Chrome or Brave browser. This acts as your wallet and is necessary for deploying contracts.

Deployment:

  • To simulate a deposit in Remix, switch to the Deploy & Run Transactions tab, select the Environment as “Injected Provider — Metamask”, cross check the Address and Network.
  • While Deploying add the “Owners address” in array like [“ox…”,….,”0x..”] and Add confiramtion Required count.
  • Click on the “Transact” button.
    Image description

  • After deployment, you can deposit XDC into the contract by sending XDC to its address(i.e in MultiSig Wallet).
    Image description

Contract Interaction

1. Submit Transaction

  • Call the submitTransaction function with the desired parameters: the recipient address (_to), value (_value) (*add value with 18 ZERO’s), and optional data (_data). This function can only be called by one of the contract owners.

Image description

  • Once you Submitted the transaction, you will get the “txId” in the console
    Image description

  • You can check the transaction status by calling “transactions” GET function.
    Image description

2. Confirm Transaction:

  • After a transaction is submitted, other owners need to confirm it before it can be executed.
  • Each owner can confirm the transaction by calling the confirmTransaction function with the transaction ID (_txId). This function can only be called by the contract owners who haven't already confirmed the transaction.

Image description

3. Execute Transaction:

  • Once the required number of confirmations is reached, any owner can execute the transaction.
  • Call the executeTransaction function with the transaction ID (_txId). This function checks if the transaction is confirmed and executes it if so.
    Image description

  • If the transaction is successful, the Execution event is emitted. If not, the ExecutionFailure event is emitted.
    Image description

  • Once Execution done successfully, the transaction executed status will be TRUE
    Image description

Additional Steps for Using Hardhat with TypeScript:

Install and set up Hardhat, a development environment for compiling, testing, and deploying your contracts. This requires Node.js and npm.

  • Write your contract, compile it using Hardhat, and write a deployment script.
  • Add XDC network configuration to your Hardhat project to enable deployment to the XDC Network. This will involve specifying the network URL and your private key in a .env file for secure access.
  • Use Hardhat’s command line to run your deployment script, targeting the XDC network.

Remember, deploying smart contracts involves transactions that cost gas fees, so ensure you have enough XDC tokens for the process. Also, consider testing thoroughly on the testnet before deploying to the mainnet to avoid potential issues and losses.
For detailed instructions, you can follow the guides on deploying with XDC Remix and XDCPay and deploying using Hardhat with TypeScript on the XDC Network.

Creating, testing, and deploying smart contracts on the XDC Network also requires an understanding of smart contracts’ workings, unique features of the XDC Network like its XDPoS consensus mechanism, and how these factors make it an efficient platform for dApps and tokens as detailed on https://xinfin.org/quick-tools-guide or any issue please post issue with all possible details (including screenshot) at : XDC.Dev

Conclusion:
Multi-Signature wallets offer a robust solution for enhancing security and control in the world of blockchain and cryptocurrency. By distributing control among multiple parties, they mitigate the risk of unauthorized access and potential vulnerabilities. As the adoption of blockchain technology continues to grow, Multi-Sig wallets are poised to play a crucial role in safeguarding digital assets and facilitating secure transactions in the decentralized ecosystem.

Discussion (0)