Skip to content

Instantly share code, notes, and snippets.

@obalcells
Created October 31, 2019 23:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save obalcells/066cebe3179e4f2c9416a34759704fd5 to your computer and use it in GitHub Desktop.
Save obalcells/066cebe3179e4f2c9416a34759704fd5 to your computer and use it in GitHub Desktop.
Smart Contract sample for display
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