Files
CurrenciCombo/contracts/MultiSigWallet.sol
defiQUG f600b7b15e Add ECDSA signature verification and enhance ComboHandler functionality
- Integrated ECDSA for signature verification in ComboHandler.
- Updated event emissions to include additional parameters for better tracking.
- Improved gas tracking during execution of combo plans.
- Enhanced database interactions for storing and retrieving plans, including conflict resolution and status updates.
- Added new dependencies for security and database management in orchestrator.
2025-11-05 16:28:48 -08:00

130 lines
4.1 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title MultiSigWallet
* @notice Multi-signature wallet for admin functions
* @dev Requires multiple signatures for critical operations
*/
contract MultiSigWallet {
address[] public owners;
uint256 public required;
mapping(bytes32 => bool) public executed;
event Deposit(address indexed sender, uint256 amount);
event SubmitTransaction(uint256 indexed txIndex, address indexed owner, address indexed to, uint256 value, bytes data);
event ConfirmTransaction(uint256 indexed txIndex, address indexed owner);
event RevokeConfirmation(uint256 indexed txIndex, address indexed owner);
event ExecuteTransaction(uint256 indexed txIndex, address indexed owner);
modifier onlyOwner() {
require(isOwner(msg.sender), "Not owner");
_;
}
modifier txExists(uint256 _txIndex) {
require(_txIndex < transactions.length, "Transaction does not exist");
_;
}
modifier notExecuted(uint256 _txIndex) {
require(!transactions[_txIndex].executed, "Transaction already executed");
_;
}
modifier notConfirmed(uint256 _txIndex) {
require(!confirmations[_txIndex][msg.sender], "Transaction already confirmed");
_;
}
struct Transaction {
address to;
uint256 value;
bytes data;
bool executed;
}
Transaction[] public transactions;
mapping(uint256 => mapping(address => bool)) public confirmations;
constructor(address[] memory _owners, uint256 _required) {
require(_owners.length > 0, "Owners required");
require(_required > 0 && _required <= _owners.length, "Invalid required");
owners = _owners;
required = _required;
}
receive() external payable {
emit Deposit(msg.sender, msg.value);
}
function isOwner(address addr) public view returns (bool) {
for (uint256 i = 0; i < owners.length; i++) {
if (owners[i] == addr) return true;
}
return false;
}
function submitTransaction(address _to, uint256 _value, bytes memory _data) public onlyOwner returns (uint256) {
uint256 txIndex = transactions.length;
transactions.push(Transaction({
to: _to,
value: _value,
data: _data,
executed: false
}));
emit SubmitTransaction(txIndex, msg.sender, _to, _value, _data);
confirmTransaction(txIndex);
return txIndex;
}
function confirmTransaction(uint256 _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) notConfirmed(_txIndex) {
confirmations[_txIndex][msg.sender] = true;
emit ConfirmTransaction(_txIndex, msg.sender);
if (isConfirmed(_txIndex)) {
executeTransaction(_txIndex);
}
}
function revokeConfirmation(uint256 _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) {
require(confirmations[_txIndex][msg.sender], "Transaction not confirmed");
confirmations[_txIndex][msg.sender] = false;
emit RevokeConfirmation(_txIndex, msg.sender);
}
function executeTransaction(uint256 _txIndex) public txExists(_txIndex) notExecuted(_txIndex) {
require(isConfirmed(_txIndex), "Transaction not confirmed");
Transaction storage transaction = transactions[_txIndex];
transaction.executed = true;
(bool success, ) = transaction.to.call{value: transaction.value}(transaction.data);
require(success, "Transaction execution failed");
emit ExecuteTransaction(_txIndex, msg.sender);
}
function isConfirmed(uint256 _txIndex) public view returns (bool) {
uint256 count = 0;
for (uint256 i = 0; i < owners.length; i++) {
if (confirmations[_txIndex][owners[i]]) count++;
if (count == required) return true;
}
return false;
}
function getTransactionCount() public view returns (uint256) {
return transactions.length;
}
function getOwners() public view returns (address[] memory) {
return owners;
}
}