Created
October 31, 2019 23:35
-
-
Save obalcells/066cebe3179e4f2c9416a34759704fd5 to your computer and use it in GitHub Desktop.
Smart Contract sample for display
This file contains 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
contract Acta { | |
mapping (uint => mapping (address => bool)) public votes; | |
mapping (address => bool) public isMember; | |
mapping (address => Member) public members; | |
mapping (bytes32 => address) public nameToAddress; | |
mapping (uint => Proposal) public proposals; | |
uint public nRequiredVotes = 1; | |
uint public nProposals = 0; | |
uint public nMembers = 0; | |
//A member is an organization such as a research lab which was | |
//previously accepted into the network by the rest of the members. | |
//Each member participating in the network must be registered with a | |
//human-readable name, an Ethereum account for interacting with this | |
//smart contract and a gateway to its API | |
struct Member { | |
bytes32 name; | |
bytes32 gateway; | |
address addr; | |
} | |
//Since RedMedic is a decentralized consortium of providers, changes in the system | |
//such as the inclusion of a new member are voted democratically. | |
//For a change to be executed, it has to be instantiated as a proposal and have nRequiredVotes in favor. | |
//There are different types of proposals. Each one follows the same | |
//structure but makes use of different data fields. | |
//Here are the different ids and what they stand for: | |
// 1 => new member join | |
// 2 => kick member out | |
// 3 => change required amount of confirmations for proposals to be executed | |
// 4 => send x amount of contract's funds to specified address | |
struct Proposal { | |
uint proposalId; | |
uint numData; | |
bytes32 bytesData1; | |
bytes32 bytesData2; | |
address addrData; | |
uint nVotes; | |
} | |
//This function gets executed during the creation of the smart contract. | |
//It sets the creator of the SC as the only registered member. | |
constructor(bytes32 name, bytes32 gateway) public { | |
require(nMembers == 0); | |
members[msg.sender] = Member({ | |
name: name, | |
gateway: gateway, | |
addr: msg.sender | |
}); | |
isMember[msg.sender] = true; | |
nMembers++; | |
} | |
//It adds a proposal to the list of unexecuted proposals where it will be voted | |
function internalActionProposal(uint proposalId, uint numData, bytes32 bytesData1, bytes32 bytesData2, address addrData) private { | |
proposals[nProposals] = Proposal({ | |
proposalId: proposalId, | |
numData: numData, | |
bytesData1: bytesData1, | |
bytesData2: bytesData2, | |
addrData: addrData, | |
nVotes: 0 | |
}); | |
nProposals++; | |
emit ProposalSaved("ProposalSaved", msg.sender, proposalId, numData, bytesData1, bytesData2, addrData); | |
} | |
//Someone sends this contract join request. It will have to pay | |
//0.1 ether to the contract to avoid spam requests and the request | |
//will get formalized as a Proposal which will later get voted by members | |
function joinRequest(bytes32 name, bytes32 gateway) public payable { | |
//checks that | |
require(isMember[msg.sender] == false && msg.value >= 0.1 ether); | |
emit JoinRequest("JoinRequest", msg.sender, name, msg.value); | |
internalActionProposal(1, 0, name, gateway, msg.sender); | |
} | |
//These functions instantiate different internal proposals. | |
//Therefore only registered members can call them. | |
function addMemberProposal(bytes32 name, bytes32 gateway, address addr) public {...} | |
function kickMemberProposal(bytes32 name, address addr) public {...} | |
function changeRequiredVotesProposal(uint newRequirement) public {...} | |
function transferFundsProposal(uint amount, bytes32 receiverName, address receiverAddr) public {...} | |
//Only registered members can call this funcion to be able to vote a proposal. | |
//If the proposal has nRequiredVotes, it will automatically get executed | |
function voteProposal(uint proposalIndex) public { | |
//checks that sender of the tx is registered member, checks that proposal exists and checks that the member hasn't called it already | |
require(isMember[msg.sender] && proposals[proposalIndex].proposalId > 0 && votes[proposalIndex][msg.sender] == false); | |
//proposal gets voted by the caller of this function | |
votes[proposalIndex][msg.sender] = true; | |
proposals[proposalIndex].nVotes++; | |
emit ProposalVoted("ProposalVoted", proposalIndex, proposals[proposalIndex].nVotes, nRequiredVotes); | |
//if it has enough votes, it gets executed | |
if(proposals[proposalIndex].nVotes >= nRequiredVotes) executeProposal(proposalIndex); | |
} | |
//Does almost the same as the previous function but for undoing | |
//a previous vote on a non-executed proposal | |
function undoVoteProposal(uint proposalIndex) public {...} | |
//Only the contract can call this function which executes a proposal | |
//located at index proposalIndex in the list of proposals | |
function executeProposal(uint proposalIndex) private { | |
//Checks that proposal exists and has enoough amount of votes | |
require(proposals[proposalIndex].proposalId > 0 && proposals[proposalIndex].nVotes >= nRequiredVotes); | |
//Instantiate a proposal object to spare code later | |
Proposal memory proposal = proposals[proposalIndex]; | |
//Deletes the proposal from the non-executed list | |
delete proposals[proposalIndex]; | |
nProposals--; | |
if(proposal.proposalId == 1) {...} //Includes organization in the member list | |
else if(proposal.proposalId == 2) {...} //Kicks member out of the member list | |
else if(proposal.proposalId == 3) {...} //Changes the required number of votes to execute proposals in the future | |
else if(proposal.proposalId == 4) {...} //Sends contract's funds to selected ethereum address | |
//Notifies externally | |
} | |
//Functions for querying externally this contract to ask about data: | |
//Returns if a certain Ethereum Address is a registered member | |
function _isMember(address addr) public view returns (bool) { if(isMember[addr]) return true; else return false; } | |
//Returns data about a specific member. For example to ask about the gateway | |
function getMember(address addr) public view returns (bytes32, bytes32) { return (members[addr].name, members[addr].gateway); } | |
//Returns the Ethereum Address of a member name | |
function getAddressByName(bytes32 name) public view returns (address) { return nameToAddress[name]; } | |
//Returns a Proposal based on the index provided | |
function getProposal(uint proposalIndex) public view returns (uint, uint, bytes32, bytes32, address, uint) { | |
return (proposals[proposalIndex].proposalId, proposals[proposalIndex].numData, proposals[proposalIndex].bytesData1, | |
proposals[proposalIndex].bytesData2, proposals[proposalIndex].addrData, proposals[proposalIndex].nVotes); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment