Skip to content

Instantly share code, notes, and snippets.

@serapath
Created May 3, 2018 07:31
Show Gist options
  • Save serapath/13333d884a938f4762f6f87482270cc2 to your computer and use it in GitHub Desktop.
Save serapath/13333d884a938f4762f6f87482270cc2 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.23+commit.124ca40d.js&optimize=false&gist=

README

Install and Setup Metamask Extension for Chrome Browser and open Remix

  1. Install chrome extension : go to https://metamask.io/ and install chrome extension
  2. Open Metamask : click metamask extension icon to open metamask overlay
  3. Signup or Import : accept terms and follow steps to restore or create a new vault
  4. Switch to Ropsten : click network dropdown menu and choose Ropsten Test Network
  5. Create ropsten account : click first dropdown in upper right corner and click create account
  6. Open test ether faucet : click buy and then click ropsten test faucet to open faucet page
  7. Request test ether : click request 1 ether from faucet, then click transaction link
  8. Await mining : wait on etherscan until status switches to success
  9. Re-open remix : go to https://remix.ethereum.org
  10. Open run tab : in the devtools panel on the right, click the Run tab
  11. Switch remix to ropsten : click on Environment dropdown and choose Injected Web3

Load tutorial files and setup contracts

  1. Enter load command : type remix:loadgist 1483e5599012c3783def91ead259ece8 into terminal
  2. Load tutorial : press in terminal and click gist in file explorer on the left
  3. Open dependencies.txt : click dependencies.txt in the file explorer to open file in editor
  4. Load dependencies : type remix:batch in terminal, the press
  5. Explorer dependencies : click github in file explorer pane to explore all imported files
  6. Open AwardToken.sol : click gist/AwardToken.sol in file explorer to show it in the editor
  7. Compile : click on Compile tab and click Start to compile
  8. Wait for compilation : Wait until dropdown input field in compile tab shows AwardToken
  9. Choose owner account : click on Run tab and select owner address from Account dropdown
  10. Choose contract : click gist/AwardToken.sol in file explorer to show it in editor
  11. Deploy to ropsten : on Run tab click dropdown, select AwardToken + click deploy
  12. Confirm transaction : see below => ## Confirm Transactions in Metamask Popup // when transaction is successfully mined, a dapp interface will be generated in the run tab
  13. publish contract address : click copy icon on generated AwardToken dapp dropdown and share it // the address can be coded into a dapp to enable users to conveniently interact with the contract

Confirm Transactions in Metamask Popup

// blue function buttons are read only & free, pink function buttons change state and cost ether

  1. Set max gas price : Type e.g. 1 into the Gas price input field if not prefilled yet
  2. Allow transaction : click submit button to pay and send the transaction // a pending transaction log appears in terminal and updates upon success or fail
  3. Await confirmation : click etherscan link in terminal to check status details of transaction

Contract Administration (start round)

  1. Start Round : click the pink startRound function button on the awardToken udapp // round will be open for 7 hours after which the owner can close it which mints 100 tokens to the winner
  2. Confirm transaction : see above => ## Confirm Transactions in Metamask Popup

User Interaction (make proposal and vote)

  1. Select AwardToken : select AwardToken from dropdown in remix devtools panel on Run tab
  2. Connect to contract : paste AwardToken address into At address input field + click blue button
  3. Lookup ballot Address : click the currBallot button to get Ballot contract address
  4. Copy ballot address : check dapp or expanded terminal log to copy the address to clipboard
  5. Select ballot : select Ballot from dropdown in remix devtools panel on Run tab
  6. Connect to contract : paste ballot address into At address input field and click blue button // a ballot dapp will be generated on the bottom of devtools run tab
  7. Copy account address : on devtools Run tab click copy icon after Account dropdown
  8. Goto ballot dapp : scroll down on Run tab to ballot contract udapp
  9. Expand addProposal : expand the pink addProposal button by clicking arrow down after input field
  10. Add description : fill desc: input with your proposal description text (in quotation marks)
  11. Add title : fill title: input with a short title for your proposal (in quotation marks)
  12. Add your address : fill targetAddr: by pasting (ctrl+v) your account address
  13. Submit proposal : click pink transact button to send proposal // every address can only create one proposal
  14. Confirm transaction : see above => ## Confirm Transactions in Metamask Popup
  15. Lookup proposal address : click the blue getProposals button and copy a proposal address
  16. Lookup proposal details : click the blue proposals button after pasting the proposal address
  17. Vote for proposal : paste proposal address into pink vote input field and press vote button
  18. Confirm transaction : see above => ## Confirm Transactions in Metamask Popup

Contract Administration (close round)

  1. Timeout round : wait for 7 hours or press pink timeoutEarly button
  2. Confirm transaction : see above => ## Confirm Transactions in Metamask Popup
  3. Close round : click the pink closeRound button to finish round and mint 100 to winner
  4. Confirm transaction : see above => ## Confirm Transactions in Metamask Popup

User Interaction (check status)

  1. check winner : click blue winningProposal on ballot to see address of winner
  2. check Ballot : click blue currBallot on AwardToken to see active ballot gone
  3. check previous winner : click blue getPreviousWinners to see winner added to hall of fame
  4. copy winner address : select and copy address of winning proposal (ctrl+c)
  5. check balance of winner : paste winner address into blue balanceOf input field and click button // see the winner now owns a token supply of 100 freshly minted tokens
  6. check total supply : click totalSupply to see number of all minted tokens is 100
import "github/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/MintableToken.sol";
import "gist/Ballot.sol";
contract AwardToken is MintableToken {
uint quantity;
uint ballotPeriod = 7 hours;
Ballot public currBallot;
address[] public prevWinners;
event log (string _msg);
event winLog (address _win);
event newBallot (address _addr);
function AwardToken () {
quantity = 100;
}
function getPreviousWinners() constant returns (address[]) {
return prevWinners;
}
// either a name change or it works fine without it
// function approve(address spender, uint256 value) public returns (bool);
function startRound() onlyOwner canMint public returns (bool) {
// if this is the first minting then we should let this go immediately
if (address(currBallot) == 0x0) {
currBallot = new Ballot(ballotPeriod);
newBallot(currBallot);
} else {
return false;
}
}
function closeRoundEarly () onlyOwner {
if (address(currBallot) != 0x0 && !currBallot.timeOut()) {
currBallot.finish();
} else revert();
}
function closeRound() onlyOwner {
// this can only be done by the owner of the contract
if (address(currBallot) != 0x0 && currBallot.timeOut()) {
// get winner
address winner = currBallot.winningProposal();
winLog(winner);
// send to winner - but first make sure the address is valid
if ( winner == 0x0){
log("no winner");
} else {
winLog(winner);
super.mint(winner, quantity);
prevWinners.push(winner);
}
delete currBallot;
// start new round
}else revert();
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
revert();
}
function approve(address _spender, uint256 _value) public returns (bool) {
revert();
}
function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
revert();
}
function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
revert();
}
function transfer(address _to, uint256 _value) public returns (bool) {
revert();
}
}
pragma solidity ^0.4.0;
contract Ballot {
uint _duration;
uint _startTime;
bool _finishEarly;
struct Proposal {
string description;
string title;
uint voteCount;
address targetAddress;
}
event log (string _msg);
address chairperson;
mapping(address => mapping (address => uint8)) voters; // map between proposal and voter and votes
mapping(address => Proposal) public proposals;
address[] public proposalsSender;
function getProposals() constant returns (address[]) {
return proposalsSender;
}
/// Create a new ballot with $(_numProposals) different proposals.
function Ballot(uint duration) public {
chairperson = msg.sender;
_duration = duration;
_startTime = now;
_finishEarly = false;
}
// duration issues...
// add a new proposals
function addProposal(string desc, string title, address targetAddr) public {
if (timeOut() || targetAddr == 0x0 || proposals[msg.sender].targetAddress != 0x0){
revert();
}
proposals[msg.sender].description = desc;
proposals[msg.sender].title = title;
proposals[msg.sender].voteCount = 0;
proposals[msg.sender].targetAddress = targetAddr;
proposalsSender.push(msg.sender);
}
/// Give a single vote to proposal $(toProposal).
function vote(address proposal) public {
// is this msg.sender in vote - the voter the proposal or the owner of the contract?
// apparantly you can't vote more than once
uint8 vote = voters[proposal][msg.sender];
// the revert - takes it back to the initial state - but that blows away everyting - I suppose...
// check on revert();
if (timeOut()) revert();
if (vote != 0) {
revert(); // already voted for this proposal
} else {
voters[proposal][msg.sender] = 1;
proposals[proposal].voteCount += 1;
}
}
function finish() {
if (chairperson == msg.sender) _startTime = now - _duration;
else revert();
}
// timeOut vs duration in voteCount
// for use in vote(), addProposal(),
function timeOut() public constant returns ( bool timeOver) {
if (_startTime + _duration > now){
timeOver = false;
}else timeOver = true;
}
function winningProposal() public constant returns (address currLeader) {
// does this need to be run only by the contract owner? Currently I think it is not limited
uint vote = 0;
if (timeOut()){
// timeOut - mean that at least the _duration is over
// what if there is tie?
if(proposalsSender.length > 0) {
for (uint8 k = 0; k < proposalsSender.length; k++) {
Proposal proposal = proposals[proposalsSender[k]];
if (vote < proposal.voteCount) {
vote = proposal.voteCount;
currLeader = proposal.targetAddress;
}
}
if (vote > 0) {
return currLeader;
}else{
log("aint no voters!");
}
}else{
log("aint no proposals!");
}
}
}
}
remix:loadurl https://github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/MintableToken.sol
remix:loadurl https://github.com/OpenZeppelin/zeppelin-solidity/contracts/ownership/Ownable.sol
remix:loadurl https://github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/StandardToken.sol
remix:loadurl https://github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/ERC20.sol
remix:loadurl https://github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/BasicToken.sol
remix:loadurl https://github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol
remix:loadurl https://github.com/OpenZeppelin/zeppelin-solidity/contracts/math/SafeMath.sol
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment