Skip to content

Instantly share code, notes, and snippets.

@zmitton
Created October 20, 2018 02:28
Show Gist options
  • Save zmitton/36ceeb76b92d738f61292a75357571cd to your computer and use it in GitHub Desktop.
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=
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;
}
}
}
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;
}
}
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--;
}
}
// 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];
}
}
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