Last active
June 8, 2022 10:46
-
-
Save sagaratalatti/9d2b9503798ae97c57f3dc51d64cc81a to your computer and use it in GitHub Desktop.
Partnership Smartcontract
This file contains hidden or 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: GPL-3.0 | |
pragma solidity ^0.8.6; | |
import "@openzeppelin/contracts/security/Pausable.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "@openzeppelin/contracts/utils/math/SafeMath.sol"; | |
import "@openzeppelin/contracts/utils/Context.sol"; | |
import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; | |
contract Partnership is Pausable, Ownable, ReentrancyGuard { | |
using SafeMath for uint256; | |
event PayeeAdded(address account, uint256 shares); | |
event PayeeRemoved(address account, uint256 shares); | |
event PaymentReleased(address to, uint256 amount); | |
event PaymentReceived(address from, uint256 amount); | |
uint256 private _totalShares; | |
uint256 private _totalReleased; | |
uint256 private _totalPartners; | |
uint256 private _totalVoters; | |
mapping(address => uint256) private _released; | |
bool public closePartnership; | |
bool public consensus; | |
struct Partner { | |
uint weight; | |
bool voted; | |
uint vote; | |
uint shares; | |
bool isPartner; | |
} | |
struct ManagementProposal { | |
string title; | |
string proposal; | |
uint voteCount; | |
address createdBy; | |
address addressedTo; | |
bool shareChange; | |
bool voting; | |
} | |
struct Proposal { | |
string title; | |
string proposal; | |
uint voteCount; | |
address createdBy; | |
} | |
mapping(address => Partner) public partners; | |
mapping(uint => ManagementProposal) public mProposals; | |
mapping(uint256 => Proposal) public proposals; | |
constructor(address[] memory _partners, uint256[] memory _shares) public payable { | |
require(_partners.length > 0, "PaymentSplitter: no payees"); | |
for(uint256 i = 0; i < _partners.length; i++) { | |
partners[_partners[i]].isPartner = true; | |
partners[_partners[i]].shares = _shares[i]; | |
partners[_partners[i]].vote = 1; | |
} | |
} | |
receive() external payable virtual { | |
emit PaymentReceived(_msgSender(), msg.value); | |
} | |
function totalShares() public view returns (uint256) { | |
return _totalShares; | |
} | |
function totalReleased() public view returns (uint256) { | |
return _totalReleased; | |
} | |
function shares(address account) public view returns (uint256) { | |
return partners[account].shares; | |
} | |
function released(address account) public view returns(uint256) { | |
return _released[account]; | |
} | |
function release(address payable account) public virtual nonReentrant whenNotPaused { | |
require(partners[account].shares > 0, 'PaymentSplitter: account has no shares'); | |
uint256 totalReceived = address(this).balance.add(_totalReleased); | |
uint256 payment = totalReceived.mul(partners[account].shares).div(_totalShares).sub(_released[account]); | |
require(payment != 0, 'PaymentSplitter: account is not due payment'); | |
_released[account] = _released[account].add(payment); | |
_totalReleased = _totalReleased.add(payment); | |
account.transfer(payment); | |
emit PaymentReleased(account, payment); | |
} | |
function _removePayee(address account, uint256 shares_) internal onlyOwner whenNotPaused { | |
require(account != address(0), 'PaymentSplitter: account is the zero address'); | |
require(shares_ < 0, 'PaymentSplitter: account already has shares'); | |
partners[account].shares = 0; | |
_totalShares = _totalShares.sub(shares_); | |
emit PayeeRemoved(account, partners[account].shares); | |
} | |
function pause() public onlyOwner { | |
_pause(); | |
} | |
function unpause() public onlyOwner { | |
_unpause(); | |
} | |
modifier onlyPartners(address partner) { | |
require(partners[partner].weight == 1, 'You are not a partner!'); | |
_; | |
} | |
function makeProposal(string memory _title, string memory _proposal, uint256 _proposalNumber) public onlyPartners(msg.sender) { | |
proposals[_proposalNumber].title = _title; | |
proposals[_proposalNumber].proposal = _proposal; | |
proposals[_proposalNumber].voteCount = 0; | |
proposals[_proposalNumber].createdBy = msg.sender; | |
} | |
function propForRightToVote(address partner, uint256 _proposalNumber, string memory _title, string memory _proposal) external onlyPartners(msg.sender) whenNotPaused{ | |
mProposals[_proposalNumber].title = _title; | |
mProposals[_proposalNumber].proposal = _proposal; | |
mProposals[_proposalNumber].voteCount = 0; | |
mProposals[_proposalNumber].createdBy = msg.sender; | |
mProposals[_proposalNumber].addressedTo = partner; | |
mProposals[_proposalNumber].shareChange = false; | |
mProposals[_proposalNumber].voting = true; | |
} | |
function propRightToVoteConsensus(uint _proposalNumber) public onlyOwner { | |
require(mProposals[_proposalNumber].voting == true, 'Proposal not for right to vote'); | |
require(mProposals[_proposalNumber].voteCount > _totalVoters.div(2), 'No majority votes'); | |
giveRightToVote(mProposals[_proposalNumber].addressedTo); | |
} | |
function giveRightToVote(address partner) internal onlyOwner { | |
require(!partners[partner].voted, 'You have already voted.'); | |
require(partners[partner].weight == 0, 'You are already allowed to vote'); | |
partners[partner].weight = 1; | |
_totalVoters.add(1); | |
} | |
function propForRemoveVoting(address partner, uint256 _proposalNumber, string memory _title, string memory _proposal) external onlyPartners(msg.sender) whenNotPaused { | |
mProposals[_proposalNumber].title = _title; | |
mProposals[_proposalNumber].proposal = _proposal; | |
mProposals[_proposalNumber].voteCount = 0; | |
mProposals[_proposalNumber].createdBy = msg.sender; | |
mProposals[_proposalNumber].addressedTo = partner; | |
mProposals[_proposalNumber].shareChange = false; | |
mProposals[_proposalNumber].voting = false; | |
} | |
function removeVoteConsensus(uint _proposalNumber) external onlyOwner whenNotPaused { | |
require(mProposals[_proposalNumber].voting == false, 'Proposal not for right to vote'); | |
require(mProposals[_proposalNumber].voteCount > _totalVoters.div(2), 'No majority votes'); | |
renounceRightToVote(mProposals[_proposalNumber].addressedTo); | |
} | |
function renounceRightToVote(address partner) internal onlyOwner { | |
require(partners[partner].voted, 'You have not voted.'); | |
require(partners[partner].weight == 1, 'You are not allowed to vote'); | |
partners[partner].weight = 0; | |
_totalVoters.sub(1); | |
} | |
function voteForApproval(string memory _title, address partner, string memory _proposal, uint256 _proposalNumber) external onlyOwner { | |
mProposals[_proposalNumber].title = _title; | |
mProposals[_proposalNumber].proposal = _proposal; | |
mProposals[_proposalNumber].voteCount = 0; | |
mProposals[_proposalNumber].createdBy = msg.sender; | |
mProposals[_proposalNumber].addressedTo = partner; | |
} | |
function approveOnConsensus(uint256 _proposalNumber, uint share) public onlyOwner { | |
require(mProposals[_proposalNumber].voteCount > _totalVoters.div(2), 'Proposal does not have majority votes'); | |
addPartner(mProposals[_proposalNumber].addressedTo, share); | |
} | |
function addPartner(address partner, uint shares_) internal onlyOwner { | |
require(partner != address(0), 'PaymentSplitter: account is the zero address'); | |
require(shares_ > 0, 'PaymentSplitter: account already has shares'); | |
partners[partner].shares = shares_; | |
_totalShares = _totalShares.add(shares_); | |
emit PayeeAdded(partner, shares_); | |
partners[partner].isPartner = true; | |
} | |
function voteForRemoval(string memory _title, address partner, string memory _proposal, uint256 _proposalNumber) external onlyPartners(msg.sender){ | |
require(partners[partner].isPartner == true, 'Recipient is not a partner'); | |
mProposals[_proposalNumber].title = _title; | |
mProposals[_proposalNumber].proposal = _proposal; | |
mProposals[_proposalNumber].voteCount = 0; | |
mProposals[_proposalNumber].createdBy = msg.sender; | |
mProposals[_proposalNumber].addressedTo = partner; | |
} | |
function removeOnConsensus(uint256 _proposalNumber) public onlyOwner { | |
require(mProposals[_proposalNumber].voteCount > _totalVoters.div(2), 'Proposal does not have majority votes'); | |
removePartner(mProposals[_proposalNumber].addressedTo); | |
} | |
function removePartner(address partner) internal onlyOwner { | |
delete partners[partner]; | |
} | |
function vote(uint proposal) external onlyPartners(msg.sender) whenNotPaused nonReentrant { | |
Partner storage partner = partners[msg.sender]; | |
require(partner.weight != 0, 'You have no right to vote'); | |
require(!partner.voted, 'You have already voted'); | |
partner.voted = true; | |
partner.vote = proposal; | |
proposals[proposal].voteCount += partner.weight; | |
} | |
function readProposal(uint _proposalNumber) public onlyPartners(msg.sender) view returns (string memory _title, string memory _proposal, uint _voteCount, address _createdBy) { | |
return (proposals[_proposalNumber].title, | |
proposals[_proposalNumber].proposal, | |
proposals[_proposalNumber].voteCount, | |
proposals[_proposalNumber].createdBy); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment