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.
This commit is contained in:
129
contracts/MultiSigWallet.sol
Normal file
129
contracts/MultiSigWallet.sol
Normal file
@@ -0,0 +1,129 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user