Created
October 20, 2018 02:28
-
-
Save zmitton/36ceeb76b92d738f61292a75357571cd 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.25+commit.59dbf8f1.js&optimize=true&gist=
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
pragma solidity ^0.4.0; | |
contract Ballot { | |
struct Voter { | |
uint weight; | |
bool voted; | |
uint8 vote; | |
address delegate; | |
} | |
struct Proposal { | |
uint voteCount; | |
} | |
address chairperson; | |
mapping(address => Voter) voters; | |
Proposal[] proposals; | |
/// Create a new ballot with $(_numProposals) different proposals. | |
function Ballot(uint8 _numProposals) public { | |
chairperson = msg.sender; | |
voters[chairperson].weight = 1; | |
proposals.length = _numProposals; | |
} | |
/// Give $(toVoter) the right to vote on this ballot. | |
/// May only be called by $(chairperson). | |
function giveRightToVote(address toVoter) public { | |
if (msg.sender != chairperson || voters[toVoter].voted) return; | |
voters[toVoter].weight = 1; | |
} | |
/// Delegate your vote to the voter $(to). | |
function delegate(address to) public { | |
Voter storage sender = voters[msg.sender]; // assigns reference | |
if (sender.voted) return; | |
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) | |
to = voters[to].delegate; | |
if (to == msg.sender) return; | |
sender.voted = true; | |
sender.delegate = to; | |
Voter storage delegateTo = voters[to]; | |
if (delegateTo.voted) | |
proposals[delegateTo.vote].voteCount += sender.weight; | |
else | |
delegateTo.weight += sender.weight; | |
} | |
/// Give a single vote to proposal $(toProposal). | |
function vote(uint8 toProposal) public { | |
Voter storage sender = voters[msg.sender]; | |
if (sender.voted || toProposal >= proposals.length) return; | |
sender.voted = true; | |
sender.vote = toProposal; | |
proposals[toProposal].voteCount += sender.weight; | |
} | |
function winningProposal() public constant returns (uint8 _winningProposal) { | |
uint256 winningVoteCount = 0; | |
for (uint8 prop = 0; prop < proposals.length; prop++) | |
if (proposals[prop].voteCount > winningVoteCount) { | |
winningVoteCount = proposals[prop].voteCount; | |
_winningProposal = prop; | |
} | |
} | |
} |
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
pragma solidity ^0.4.7; | |
import "remix_tests.sol"; // this import is automatically injected by Remix. | |
import "./ballot.sol"; | |
contract test3 { | |
Ballot ballotToTest; | |
function beforeAll () { | |
ballotToTest = new Ballot(2); | |
} | |
function checkWinningProposal () public { | |
ballotToTest.vote(1); | |
Assert.equal(ballotToTest.winningProposal(), uint(1), "1 should be the winning proposal"); | |
} | |
function checkWinninProposalWithReturnValue () public constant returns (bool) { | |
return ballotToTest.winningProposal() == 1; | |
} | |
} |
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
pragma solidity 0.4.25; | |
library MaxHeap_impl { | |
struct T{ | |
uint thing; | |
} | |
struct Heap { | |
T[] data; | |
} | |
/* | |
* Implementation of Maximum Heap | |
*/ | |
function insert(Heap[T] storage _heap, T _value) | |
{ | |
_heap.data.length++; | |
for ( | |
uint _index = _heap.data.length - 1; | |
_index > 0 && _value > _heap.data[_index / 2]; | |
_index /= 2) | |
{ | |
_heap.data[_index] = _heap.data[_index / 2]; | |
} | |
_heap.data[_index] = _value; | |
} | |
function top(Heap[T] storage _heap) returns (T) | |
{ | |
return _heap.data[0]; | |
} | |
function pop(Heap[T] storage _heap) | |
{ | |
T storage last = _heap.data[_heap.data.length - 1]; | |
for ( | |
uint index = 0; | |
2 * index < _heap.data.length | |
;) | |
{ | |
uint nextIndex = 2 * index; | |
if (2 * index + 1 < _heap.data.length && _heap.data[2 * index + 1] > _heap.data[2 * index]) | |
nextIndex = 2 * index + 1; | |
if (_heap.data[nextIndex] > last) | |
_heap.data[index] = _heap.data[nextIndex]; | |
else | |
break; | |
index = nextIndex; | |
} | |
_heap.data[index] = last; | |
_heap.data.length--; | |
} | |
} |
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
// Eth Heap | |
// Author: Zac Mitton | |
// License: Use for all the things. And make lots of money with it. | |
pragma solidity 0.4.24; | |
library Heap{ // default max-heap | |
uint constant ROOT_INDEX = 1; | |
struct Data{ | |
int128 idCount; | |
Node[] nodes; // root is index 1; index 0 not used | |
mapping (int128 => uint) indices; // unique id => node index | |
} | |
struct Node{ | |
int128 id; //use with another mapping to store arbitrary object types | |
int128 priority; | |
} | |
//call init before anything else | |
function init(Data storage self) internal{ | |
if(self.nodes.length == 0) self.nodes.push(Node(0,0)); | |
} | |
function insert(Data storage self, int128 priority) internal returns(Node){//√ | |
if(self.nodes.length == 0){ init(self); }// test on-the-fly-init | |
self.idCount++; | |
self.nodes.length++; | |
Node memory n = Node(self.idCount, priority); | |
_bubbleUp(self, n, self.nodes.length-1); | |
return n; | |
} | |
function extractMax(Data storage self) internal returns(Node){//√ | |
return _extract(self, ROOT_INDEX); | |
} | |
function extractById(Data storage self, int128 id) internal returns(Node){//√ | |
return _extract(self, self.indices[id]); | |
} | |
//view | |
function dump(Data storage self) internal view returns(Node[]){ | |
//note: Empty set will return `[Node(0,0)]`. uninitialized will return `[]`. | |
return self.nodes; | |
} | |
function getById(Data storage self, int128 id) internal view returns(Node){ | |
return getByIndex(self, self.indices[id]);//test that all these return the emptyNode | |
} | |
function getByIndex(Data storage self, uint i) internal view returns(Node){ | |
return self.nodes.length > i ? self.nodes[i] : Node(0,0); | |
} | |
function getMax(Data storage self) internal view returns(Node){ | |
return getByIndex(self, ROOT_INDEX); | |
} | |
function size(Data storage self) internal view returns(uint){ | |
return self.nodes.length > 0 ? self.nodes.length-1 : 0; | |
} | |
function isNode(Node n) internal pure returns(bool){ return n.id > 0; } | |
//private | |
function _extract(Data storage self, uint i) private returns(Node){//√ | |
if(self.nodes.length <= i || i <= 0){ return Node(0,0); } | |
Node memory extractedNode = self.nodes[i]; | |
delete self.indices[extractedNode.id]; | |
Node memory tailNode = self.nodes[self.nodes.length-1]; | |
self.nodes.length--; | |
if(i < self.nodes.length){ // if extracted node was not tail | |
_bubbleUp(self, tailNode, i); | |
_bubbleDown(self, self.nodes[i], i); // then try bubbling down | |
} | |
return extractedNode; | |
} | |
function _bubbleUp(Data storage self, Node memory n, uint i) private{//√ | |
if(i==ROOT_INDEX || n.priority <= self.nodes[i/2].priority){ | |
_insert(self, n, i); | |
}else{ | |
_insert(self, self.nodes[i/2], i); | |
_bubbleUp(self, n, i/2); | |
} | |
} | |
function _bubbleDown(Data storage self, Node memory n, uint i) private{// | |
uint length = self.nodes.length; | |
uint cIndex = i*2; // left child index | |
if(length <= cIndex){ | |
_insert(self, n, i); | |
}else{ | |
Node memory largestChild = self.nodes[cIndex]; | |
if(length > cIndex+1 && self.nodes[cIndex+1].priority > largestChild.priority ){ | |
largestChild = self.nodes[++cIndex];// TEST ++ gets executed first here | |
} | |
if(largestChild.priority <= n.priority){ //TEST: priority 0 is valid! negative ints work | |
_insert(self, n, i); | |
}else{ | |
_insert(self, largestChild, i); | |
_bubbleDown(self, n, cIndex); | |
} | |
} | |
} | |
function _insert(Data storage self, Node memory n, uint i) private{//√ | |
self.nodes[i] = n; | |
self.indices[n.id] = i; | |
} | |
} | |
contract BountyHeap{ | |
using Heap for Heap.Data; | |
Heap.Data public data; | |
uint public createdAt; | |
address public author; | |
constructor(address _author) public { | |
data.init(); | |
createdAt = now; | |
author = _author; | |
} | |
function () public payable{} | |
function endBounty() public{ | |
require(now > createdAt + 2592000); //60*60*24*30 = 2592000 = 30 days | |
author.transfer(address(this).balance); //any remaining ETH goes back to me | |
} | |
function breakCompleteness(uint holeIndex, uint filledIndex, address recipient) public{ | |
require(holeIndex > 0); // 0 index is empty by design (doesn't count) | |
require(data.getByIndex(holeIndex).id == 0); //holeIndex has nullNode | |
require(data.getByIndex(filledIndex).id != 0); // filledIndex has a node | |
require(holeIndex < filledIndex); //HOLE IN MIDDLE OF HEAP! | |
recipient.transfer(address(this).balance); | |
} | |
function breakParentsHaveGreaterPriority(uint indexChild, address recipient) public{ | |
Heap.Node memory child = data.getByIndex(indexChild); | |
Heap.Node memory parent = data.getByIndex(indexChild/2); | |
require(Heap.isNode(child)); | |
require(Heap.isNode(parent)); | |
require(child.priority > parent.priority); // CHILD PRIORITY LARGER THAN PARENT! | |
recipient.transfer(address(this).balance); | |
} | |
function breakIdMaintenance(int128 id, address recipient) public{ | |
require(data.indices[id] != 0); //id exists in mapping | |
require(data.nodes[data.indices[id]].id != id); // BUT NODE HAS CONTRIDICTORY ID! | |
recipient.transfer(address(this).balance); | |
} | |
function breakIdMaintenance2(uint index, address recipient) public{ | |
Heap.Node memory n = data.getByIndex(index); | |
require(Heap.isNode(n)); //node exists in array | |
require(index != data.indices[n.id]); // BUT MAPPING DOESNT POINT TO IT! | |
recipient.transfer(address(this).balance); | |
} | |
function breakIdUniqueness(uint index1, uint index2, address recipient) public{ | |
Heap.Node memory node1 = data.getByIndex(index1); | |
Heap.Node memory node2 = data.getByIndex(index2); | |
require(Heap.isNode(node1)); | |
require(Heap.isNode(node2)); | |
require(index1 != index2); //2 different positions in the heap | |
require(node1.id == node2.id); //HAVE 2 NODES WITH THE SAME ID! | |
recipient.transfer(address(this).balance); | |
} | |
function heapify(int128[] priorities) public { | |
for(uint i ; i < priorities.length ; i++){ | |
data.insert(priorities[i]); | |
} | |
} | |
function insert(int128 priority) public returns(int128){ | |
return data.insert(priority).id; | |
} | |
function extractMax() public returns(int128){ | |
return data.extractMax().priority; | |
} | |
function extractById(int128 id) public returns(int128){ | |
return data.extractById(id).priority; | |
} | |
//view | |
// // Unfortunately the function below requires the experimental compiler | |
// // which cant be verified on etherscan or used natively with truffle. | |
// // Hopefully soon it will be standard. | |
// function dump() public view returns(Heap.Node[]){ | |
// return data.dump(); | |
// } | |
function getIdMax() public view returns(int128){ | |
return data.getMax().id; | |
} | |
function getMax() public view returns(int128){ | |
return data.getMax().priority; | |
} | |
function getById(int128 id) public view returns(int128){ | |
return data.getById(id).priority; | |
} | |
function getIdByIndex(uint i) public view returns(int128){ | |
return data.getByIndex(i).id; | |
} | |
function getByIndex(uint i) public view returns(int128){ | |
return data.getByIndex(i).priority; | |
} | |
function size() public view returns(uint){ | |
return data.size(); | |
} | |
function idCount() public view returns(int128){ | |
return data.idCount; | |
} | |
function indices(int128 id) public view returns(uint){ | |
return data.indices[id]; | |
} | |
} |
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
pragma solidity 0.4.25; | |
contract test{ | |
// uint256 constant STORAGE_LOCATION_ARRAY = 0xDEADBEEF | |
function mint(uint256 value) public { | |
uint256 storage_location_array = 0xDEADBEEF; // can't use constants inside assembly | |
if (value == 0) { | |
return; | |
} | |
// Read supply | |
uint256 supply; | |
assembly { | |
supply := sload(storage_location_array) | |
} | |
// Set memory locations in interval [l, r] | |
uint256 l = storage_location_array + supply + 1; | |
uint256 r = storage_location_array + supply + value; | |
assert(r >= l); | |
for (uint256 i = l; i <= r; i++) { | |
assembly { | |
sstore(i, 1) | |
} | |
} | |
// Write updated supply & balance | |
assembly { | |
sstore(storage_location_array, add(supply, value)) | |
} | |
} | |
uint x; | |
function spend4Million(){ | |
for(uint i = 0 ; i < 600 ; i++){ | |
x = i; | |
} | |
} | |
function freeStorage(uint256 value) public { | |
uint256 storage_location_array = 0xDEADBEEF; // can't use constants inside assembly | |
// Read supply | |
uint256 supply; | |
assembly { | |
supply := sload(storage_location_array) | |
} | |
spend4Million(); | |
// Clear memory locations in interval [l, r] | |
uint256 l = storage_location_array + supply - value + 1; | |
uint256 r = storage_location_array + supply; | |
for (uint256 i = l; i <= r; i++) { | |
assembly { | |
sstore(i, 0) | |
} | |
} | |
// Write updated supply | |
assembly { | |
sstore(storage_location_array, sub(supply, value)) | |
} | |
spend4Million(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment