// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract TeamWallet {
address public deployer; // The deployer of the contract
address[] public members; // Array to store team members
uint public totalCredits; // Total available credits in the wallet
struct Transaction {
uint amount;
bool executed;
uint approvals;
}
Transaction[] public transactions;
mapping(address => mapping(uint => bool)) public hasApproved;
mapping(address => mapping(uint => bool)) public hasRejected;
modifier onlyDeployer() {
require(msg.sender == deployer, "Only the deployer can call this function");
_;
}
modifier onlyTeamMember() {
require(isTeamMember(msg.sender), "Only team members can call this function");
_;
}
constructor() {
deployer = msg.sender;
}
function isTeamMember(address _address) internal view returns (bool) {
for (uint i = 0; i < members.length; i++) {
if (members[i] == _address) {
return true;
}
}
return false;
}
function setWallet(address[] memory _members, uint _totalCredits) public onlyDeployer {
require(members.length == 0, "Wallet has already been initialized");
require(_members.length > 0, "There must be at least one team member");
require(_totalCredits > 0, "Credits must be greater than 0");
require(deployer != _members[0], "The deployer cannot be a team member");
for (uint i = 0; i < _members.length; i++) {
members.push(_members[i]);
}
totalCredits = _totalCredits;
}
function spend(uint _amount) public onlyTeamMember {
require(_amount > 0, "Amount must be greater than 0");
transactions.push(Transaction(_amount, false, 1));
hasApproved[msg.sender][transactions.length - 1] = true;
}
function approve(uint _n) public onlyTeamMember {
require(_n < transactions.length, "Invalid transaction index");
require(!hasApproved[msg.sender][_n], "Approval already recorded");
require(!hasRejected[msg.sender][_n], "Transaction already rejected");
transactions[_n].approvals++;
hasApproved[msg.sender][_n] = true;
}
function reject(uint _n) public onlyTeamMember {
require(_n < transactions.length, "Invalid transaction index");
require(!hasApproved[msg.sender][_n], "Transaction already approved");
require(!hasRejected[msg.sender][_n], "Rejection already recorded");
transactions[_n].approvals++;
hasRejected[msg.sender][_n] = true;
if (transactions[_n].approvals > members.length * 70 / 100) {
transactions[_n].executed = true;
totalCredits -= transactions[_n].amount;
}
}
function getAvailableCredits() public view onlyTeamMember returns (uint) {
return totalCredits;
}
function viewTransaction(uint _n) public view onlyTeamMember returns (uint amount, string memory status) {
require(_n < transactions.length, "Invalid transaction index");
amount = transactions[_n].amount;
if (transactions[_n].executed) {
status = "debited";
} else if (transactions[_n].approvals > members.length * 70 / 100) {
status = "pending";
} else {
status = "failed";
}
}
}