pragma solidity 0.7.5;
pragma abicoder v2;
contract Wallet {
address[] public owners;
uint limit;
struct Transfer{
uint amount;
address payable receiver;
uint approvals;
bool hasBeenSent;
uint id;
}
event TransferRequestCreated (uint _id, uint _amount, address _initiator, address _receiver);
event ApprovalReceived (uint _id, uint _approvals, address _approver);
event TransferApproved (uint _id);
Transfer[] transferRequests;
mapping(address => mapping(uint => bool)) approvals;
modifier onlyOwners(){
require (inOwnersArray() == true);
_;
}
function inOwnersArray () private view returns (bool){ //additional function that checks if msg.sender is in the owners array.
bool inArray;
for (uint i = 0; i < owners.length; i++){
if (owners[i] == msg.sender){
inArray = true;
break;
}
else {inArray = false;}
}
return inArray;
}
constructor(address[] memory _owners, uint _limit) {
owners = _owners;
limit = _limit;
}
function deposit() public payable {
mappingBalances[msg.sender] += msg.value;
}
//We keep track of balances that have been changed after transfer requests go through.
mapping (address => uint) mappingBalances;
function getAllBalances () public view returns (uint){
return mappingBalances[msg.sender];
}
function createTransfer(uint _amount, address payable _receiver) public onlyOwners {
require(_amount <= mappingBalances[msg.sender]); // Require for the sender's balance to be able to cover the transfer.
emit TransferRequestCreated(transferRequests.length, _amount, msg.sender, _receiver);
transferRequests.push(Transfer(_amount, _receiver, 0, false, transferRequests.length)); // 0 approvals at the start.
}
//Set your approval for one of the transfer requests.
//Need to update the Transfer object.
//Need to update the mapping to record the approval for the msg.sender.
//When the amount of approvals for a transfer has reached the limit, this function should send the transfer to the recipient.
//An owner should not be able to vote twice.
//An owner should not be able to vote on a tranfer request that has already been sent.
function approve(uint _id) public onlyOwners {
require(approvals[msg.sender][_id] == false);
if (transferRequests[_id].approvals < limit){
transferRequests[_id].approvals++;
emit ApprovalReceived (_id, transferRequests[_id].approvals, msg.sender);
}
approvals[msg.sender][_id] = true;
if (transferRequests[_id].approvals >= limit){
transferRequests[_id].receiver.transfer(transferRequests[_id].amount);
transferRequests[_id].hasBeenSent = true;
mappingBalances[transferRequests[_id].receiver] += transferRequests[_id].amount;
emit TransferApproved (_id);
}
}
//Should return all transfer requests
function getTransferRequests() public view returns (Transfer[] memory){
return transferRequests;
}
}
This is my solution. Iâd like some feedback on whether this could actually be used in practice and what are the things that have to be fixed.
I used the template that Filip provided and added a few more features.
Thereâs a separate function that checks whether msg.sender is included in the owners array.
I added a mapping called mappingBalances thatâs supposed to keep track of all the balances after different transfers are confirmed and go through.
Itâs also required for the msg.sender balance to have enough funds to be able to cover a requested transfer.
However, I wasnât able to figure out how to reduce the msg.sender balance for the amount of money sent in a transfer that went through. Any tips?
Thanks