pragma solidity 0.7.5;
pragma abicoder v2;
contract Wallet {
address payable owner1;
address payable owner2;
address payable owner3;
uint256 approvalLimit;
constructor() {
owner1 = msg.sender;
owner2 = msg.sender;
owner3 = msg.sender;
approvalLimit = 2;
}
modifier onlyDeveloper {
require(msg.sender == owner1);
_;
}
modifier onlyOwner {
require(msg.sender == owner1 || msg.sender == owner2 || msg.sender == owner3);
_;
}
struct transfer {
address sender;
address recipient;
uint256 amount;
bool completed;
uint256 approvals;
}
transfer[] transfers;
uint256 id = 0;
mapping(address => uint256) balance;
mapping(address => mapping(uint256 => bool)) approvalStatus;
event transferCompleted(address sender, address recipient, uint256 amount, uint256 approvals, bool owner1approval, bool owner2approval, bool owner3approval);
function setOwners(address payable _owner2Address, address payable _owner3Address) public payable onlyDeveloper returns (address, address) {
owner2 = _owner2Address;
owner3 = _owner3Address;
return (owner2, owner3);
}
function getOwners() public view returns (address, address, address) {
return (owner1, owner2, owner3);
}
function setApprovalLimit(uint256 _approvalLimit) public onlyDeveloper returns (uint256) {
approvalLimit = _approvalLimit;
require(approvalLimit > 1 && approvalLimit <= 3, "Approval limit must be either two or three.");
return (approvalLimit);
}
function getApprovalLimit() public view returns (uint256) {
return (approvalLimit);
}
function deposit() public payable returns (uint256) {
balance[msg.sender] += msg.value;
return balance[msg.sender];
}
function withdraw(uint256 _amount) public returns (uint) {
require(_amount <= balance[msg.sender], "You cannot withdraw more than your balance.");
msg.sender.transfer(_amount);
balance[msg.sender] -= _amount;
return balance[msg.sender];
}
function getBalance() public view returns (uint256) {
return balance[msg.sender];
}
function transferRequest(address _sender, address _recipient, uint256 _amount) public onlyOwner returns (string memory) {
require(balance[_sender] >= _amount, "The senders balance is not sufficient.");
require(_sender != _recipient, "Sender and recipient cannot be the same.");
transfers.push(transfer(_sender, _recipient, _amount, false, 0));
uint256 index = transfers.length;
approvalStatus[owner1][index] == false;
approvalStatus[owner2][index] == false;
approvalStatus[owner3][index] == false;
return "You have successfully submitted your transfer request! Now, please wait for it to be approved by sufficient signatories.";
}
function getAllTransfers() public view onlyOwner returns (transfer[] memory) {
transfer[] memory transfersLogOutput = new transfer[](transfers.length);
for (uint256 i = 0; i < transfers.length; i++) {
transfersLogOutput[i] = transfers[i];
}
return transfersLogOutput;
}
function getSingleTransfer(uint256 _index) public view onlyOwner returns (address sender, address recipient, uint256 amount, bool completed, uint256 approvals, bool status) {
return (transfers[_index].sender, transfers[_index].recipient, transfers[_index].amount, transfers[_index].completed, transfers[_index].approvals, approvalStatus[msg.sender][_index]);
}
function approveTransfer(uint256 _index) public onlyOwner returns (string memory) {
if(approvalStatus[msg.sender][_index] == true){
return "You have already approved this transfer.";
}
else if(transfers[_index].completed == true){
return "This transfer has already been completed.";
}
else if(transfers[_index].approvals < (approvalLimit - 1)){
approvalStatus[msg.sender][_index] = true;
transfers[_index].approvals++;
return "Thank you for your approval! We are now waiting on further signatories for the transfer to be released.";
}
else{
approvalStatus[msg.sender][_index] = true;
transfers[_index].approvals++;
id = _index;
_transfer();
return "Thank you for your approval! As sufficient signatories have now approved, the transfer has been released.";
}
}
function disapproveTransfer(uint256 _index) public onlyOwner returns (string memory) {
if(transfers[_index].completed == true){
return "This transfer has already been completed, so it can no longer be disapproved.";
}
else{
approvalStatus[msg.sender][_index] = false;
transfers[_index].approvals--;
return "You have successfully disapproved of this transfer.";
}
}
function _transfer() private {
balance[transfers[id].sender] -= transfers[id].amount;
balance[transfers[id].recipient] += transfers[id].amount;
transfers[id].completed = true;
emit transferCompleted(transfers[id].sender, transfers[id].recipient, transfers[id].amount, transfers[id].approvals, approvalStatus[owner1][id], approvalStatus[owner2][id], approvalStatus[owner3][id]);
}
}
1 Like