I really enjoyed the multisig wallet project - it was designed in a very good way to have to use a lot of the lessons in the first videos and readings.
I have some previous experience coding and was able to mostly complete this without watching the videos, although, I had to peak at the next video titles to discover the concept of double mapping.
I was trying to solve for some of the same things using arrays but was running into trouble getting the array I created inside a function to be returned back outside the function into my TransactionRequest construct.
Another issue that tripped me for a little was that I wanted to save my list of owner accounts that I was adding in as an array to the constructor the syntax looks like this for 3 owners,
[“0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2”,“0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db”, “0x5B38Da6a701c568545dCfcB03FcB875f56beddC4”]
I pasted this after constructing it into a text editor that changed the " characters to a curly version. Remix did not like that at all! Teaches me to be using a text editor that has its own formatting in mind.
pragma solidity 0.7.5;
contract multiSigWallet {
mapping(address => uint) contributions;
mapping(address => mapping(uint => bool)) approvals;
uint balance;
uint TransactionRequestId;
uint reqApprovals;
address[] owners;
struct TransactionRequest {
uint amount;
address payable recipientAddress;
uint approvalCount;
uint status; //1 is sent, 0 is waiting additional approval
}
TransactionRequest[] TransactionRequests;
constructor(address[] memory _addresses, uint _reqApprovals){
reqApprovals = _reqApprovals;
owners = _addresses;
TransactionRequestId = 0;
}
function deposit() public payable returns (uint){
contributions[msg.sender] += msg.value;
balance += msg.value;
return contributions[msg.sender];
}
function showMyContributions() public view returns (uint){
return contributions[msg.sender];
}
function showMultiSigBalance() public view returns (uint){
return balance;
}
function getOwners() public view returns (address[] memory){
return owners;
}
function verifyAuthorization() private view {
bool approved = false;
for (uint i=0; i<owners.length; i++) {
if(owners[i] == msg.sender){
approved = true;
} else {
}
}
require(approved == true, "You are not authorized to do this.");
}
function addTransactionRequest(uint _amount, address payable _address) public{
verifyAuthorization();
/* Add the new request */
uint _oneapproval = 1; //increment approvals by 1 - the transaction requester automatically gets approved
uint _status = 0; //0 status means transaction has not been sent
TransactionRequest memory newTransactionRequest = TransactionRequest(_amount, _address, _oneapproval, _status);
TransactionRequests.push(newTransactionRequest);
/* Set all the approvals to false for this new transaction request, except the requester who is true */
for (uint i=0; i<owners.length; i++) {
approvals[owners[i]][TransactionRequestId] = false;
}
approvals[msg.sender][TransactionRequestId] = true;
TransactionRequestId++;
}
function getTransactionRequests(uint _index) public view returns (uint, address, uint, uint) {
TransactionRequest memory transactionToReturn = TransactionRequests[_index];
return (transactionToReturn.amount, transactionToReturn.recipientAddress, transactionToReturn.approvalCount, transactionToReturn.status);
}
function transfer(uint _index) public payable {
require(TransactionRequests[_index].approvalCount >= reqApprovals, "To make an approval, first request an approval as an owner, then get enough approvals from other owners");
require(TransactionRequests[_index].status == 0, "This has already been transferred");
TransactionRequests[_index].recipientAddress.transfer(TransactionRequests[_index].amount);
balance -= TransactionRequests[_index].amount;
TransactionRequests[_index].status = 1;
}
function Approve(uint _index) public {
verifyAuthorization();
/* check that the approver hasn't already approved, then mark them as already approved */
require(approvals[msg.sender][_index] == false, "You have already approved this.");
approvals[msg.sender][_index] = true;
TransactionRequests[_index].approvalCount += 1;
transfer(_index);
}