Codementor Events

Setting up a Solidity Contract for Meetup Groups

Published Jun 04, 2018
Setting up a Solidity Contract for Meetup Groups

Hello Codementor Community,

I am Sambhav Jain, sort of a blockchain researcher from New Delhi, India. This post would be my first post here so do check it out. I spent my entire last year after Fall '17 to Spring '18 in researching about the different ways in which blockchain in general could help in providing a sustainable future to the humans. Provided a limited support and exposure previously, it was quite a steep learning curve for me in the beginning. Then, I found that one of my professors at college were engaged in blockchain research. So, I mentored under him for quite sometime. I can confidently say that it is a great inexpressive working with your someone in your acquaintance.

I used to participate in regional dev meetups very often, but sometimes a major thing that continuously bugs you isn't the management but t is the inter-galactic fights between the organizers over non-mutual stances on community decisions. So, I helped in making this contract to filter out the decision-making procedure of meetup groups via a contract for running a consensus on top of the community circle.

One of the most fundamental things of going through with managing and maintaining the voice of people that are part of a particular meetup group irrespective of its domain is to align the several voices according to the community goals, while respecting and counting each one of them. This not only helps in keeping conflicts away from the group but also keeps the members more aligned towards their respective duties and deliverables as part of the group.

Not until recently, I joined a regional blockchain developer community focused around integrating Metamask in various applications they produce. I thoroughly helped in building a simple solidity contract focused on Meetup DAOs which can be further extended/edited to align with the goals of respective organizations they're setup in.

The existing features are:

  • Become a member of the DAO
  • Add or vote for proposals

All these features require to be run on the testnet in the initial phase while the team is adding the functionality for mainnet. A small amount is charged to use any feature mentioned above. Now, let's dive in the code:

Every time a contract is compiled, the parser looks out for tokens to generate, which can be more than one depending on your contract. Here's an initial setup of the structures of a proposal, member and vote. Voting is a part of the proposal procedure.

struct Proposal {
        address recipient;
        uint amount;
        string description;
        string fileHash;
        uint votingDeadline;
        bool executed;
        bool proposalPassed;
        uint numberOfVotes;
        int upvotedResult;
        int downvotedResult;
        bytes32 proposalHash;
        Vote[] votes;
        mapping (address => bool) voted;
    }

    struct Member {
        address member;
        string name;
        uint memberSince;
    }

    struct Vote {
        bool inSupport;
        address voter;
        string justification;
    }

These structs need to be encapsulated in a separate contract which must inherit several properties from other contracts defined in the code:

contract owned {
    address public owner;

    function owned()  public {
        owner = msg.sender;
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    function transferOwnership(address newOwner) onlyOwner  public {
        owner = newOwner;
    }
}

contract tokenRecipient {
    event receivedEther(address sender, uint amount);
    event receivedTokens(address _from, uint256 _value, address _token, bytes _extraData);

    function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public {
        Token t = Token(_token);
        require(t.transferFrom(_from, this, _value));
        emit receivedTokens(_from, _value, _token, _extraData);
    }

    function () payable  public {
        emit receivedEther(msg.sender, msg.value);
    }
}

interface Token {
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
}

Now, when this is done, a basic outline of the required solidity contract would be ready which can be extended to include basic functions like Add Member and Add Proposal which would be part of our main contract which inherited owned and tokenRecipent above, as follows:

function addMember(address targetMember, string memberName) onlyOwner public {
        
  // memberId is a mapping of address to unit
  uint id = memberId[targetMember];
        if (id == 0) {
            memberId[targetMember] = members.length;
            id = members.length++;
        }

        members[id] = Member({member: targetMember, memberSince: now, name: memberName});
        emit MembershipChanged(targetMember, true);
    }

function newProposal( address beneficiary, uint weiAmount, string jobDescription, string uploadFileHash, bytes transactionBytecode) onlyMembers public returns (uint proposalID) {

  // proposals in an array of Proposal struct object (see above) and other respective variables that carry their usual meaning from the names provided
        proposalID = proposals.length++;
        Proposal storage p = proposals[proposalID];
        p.recipient = beneficiary;
        p.amount = weiAmount;
        p.description = jobDescription;
        p.fileHash = uploadFileHash;
        p.proposalHash = keccak256(beneficiary, weiAmount, transactionBytecode);
        p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes;
        p.executed = false;
        p.proposalPassed = false;
        p.numberOfVotes = 0;
        emit ProposalAdded(proposalID, beneficiary, weiAmount, jobDescription);
        numProposals = proposalID+1;

        return proposalID;
    }

For more information related to the contract refer: https://github.com/BlockchainDevs/MeetupDAO/blob/master/meetupdao/contracts/solidity/dao.sol

The part where this contract meets Metamask is in the web background, asynchronously using the ABI generated by compiling the contract. The following code is part of function called to create a new member of DAO leading to call Metamask interface communicate asynchronously with the contract ABI.

var myTokenContract = web3.eth.contract(abi).at(address);
return myTokenContract.becomeMember(memberName, function (error, result) {})

One thing that I've come around which we've added in this DAO is the proposition to some contribution framework deployed on top of this system allowing existing members of the DAO to put their own projects up for contributions by other members in the group.

For more reference checkout the repo.

You may think that the title was misleading, no it wasn't. You did setup a completely auto-upgrading solidity contract for meetup groups to facilitate consensus mechanisms over the code on cloud.

Until next time.
Peace.

Discover and read more posts from Sambhav Jain
get started