Created
February 19, 2024 19:28
-
-
Save casweeney/1ec28c8bde2445b7dac941afec9ccfbc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.24; | |
contract MultiSig { | |
address owner; | |
address[] signers; | |
uint256 quorum; | |
uint256 txCount; | |
address nextOwner; | |
struct Transaction { | |
uint256 id; | |
uint256 amount; | |
address receiver; | |
uint256 signersCount; | |
bool isExecuted; | |
address txCreator; | |
} | |
Transaction[] allTransactions; | |
// mapping of transaction id to signer address returning bool: | |
// this checks if a valid signer has signed a trasaction | |
mapping (uint256 => mapping (address => bool)) hasSigned; | |
// mapping of transaction id to transaction struct | |
// used to track transactions given their ID; | |
mapping(uint256 => Transaction) transactions; | |
mapping(address => bool) isValidSigner; | |
constructor(address[] memory _validSigners, uint256 _quorum) { | |
owner = msg.sender; | |
signers = _validSigners; | |
quorum = _quorum; | |
for(uint8 i = 0; i < _validSigners.length; i++) { | |
require(_validSigners[i] != address(0), "get out"); | |
isValidSigner[_validSigners[i]] = true; | |
} | |
} | |
function initiateTransaction(uint256 _amount, address _receiver) external { | |
require(msg.sender != address(0), "zero address detected"); | |
require(_amount > 0, "no zero value allowed"); | |
onlyValidSigner(); | |
uint256 _txId = txCount + 1; | |
Transaction storage tns = transactions[_txId]; | |
tns.id = _txId; | |
tns.amount = _amount; | |
tns.receiver = _receiver; | |
tns.signersCount = tns.signersCount + 1; | |
tns.txCreator = msg.sender; | |
allTransactions.push(tns); | |
hasSigned[_txId][msg.sender] = true; | |
txCount = txCount + 1; | |
} | |
function approveTransaction(uint256 _txId) external { | |
require(_txId <= txCount, "invalid transaction id"); | |
require(msg.sender != address(0), "zero address detected"); | |
onlyValidSigner(); | |
require(!hasSigned[_txId][msg.sender], "can't sign twice"); | |
Transaction storage tns = transactions[_txId]; | |
require(address(this).balance >= tns.amount, "insufficient contract balance"); | |
require(!tns.isExecuted, "transaction already executed"); | |
require(tns.signersCount < quorum, "quorum count reached"); | |
tns.signersCount = tns.signersCount + 1; | |
hasSigned[_txId][msg.sender] = true; | |
if(tns.signersCount == quorum) { | |
tns.isExecuted = true; | |
payable(tns.receiver).transfer(tns.amount); | |
} | |
} | |
function transferOwnership(address _newOwner) external { | |
onlyOwner(); | |
nextOwner = _newOwner; | |
} | |
function claimOwnership() external { | |
require(msg.sender == nextOwner, "not next owner"); | |
owner = msg.sender; | |
nextOwner = address(0); | |
} | |
function addValidSigner(address _newSigner) external { | |
onlyOwner(); | |
require(!isValidSigner[_newSigner], "signer already exist"); | |
isValidSigner[_newSigner] = true; | |
signers.push(_newSigner); | |
} | |
function getAllTransactions() external view returns (Transaction[] memory) { | |
return allTransactions; | |
} | |
function onlyOwner() private view { | |
require(msg.sender == owner, "not owner"); | |
} | |
function onlyValidSigner() private view { | |
require(isValidSigner[msg.sender], "not valid signer"); | |
} | |
receive() external payable {} | |
fallback() external payable {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment