├── README.md ├── ERC20Token.sol └── CurationMarkets.sol /README.md: -------------------------------------------------------------------------------- 1 | For more information, read the intro & whitepaper here -> https://medium.com/@simondlr/introducing-curation-markets-trade-popularity-of-memes-information-with-code-70bf6fed9881 2 | 3 | Will flesh out this repo in due time. 4 | 5 | Code is licensed under MIT. 6 | -------------------------------------------------------------------------------- /ERC20Token.sol: -------------------------------------------------------------------------------- 1 | ppragma solidity ^0.4.10; 2 | 3 | contract ERC20Token { 4 | uint256 public totalSupply; 5 | mapping(address => uint256) public balances; 6 | mapping (address => mapping (address => uint256)) allowed; 7 | 8 | function transfer(address _to, uint256 _value) returns (bool success) { 9 | if (balances[msg.sender] >= _value) { 10 | balances[msg.sender] -= _value; 11 | balances[_to] += _value; 12 | Transfer(msg.sender, _to, _value); 13 | return true; 14 | } else { return false; } 15 | } 16 | 17 | function transferFrom(address _from, address _to, uint256 _value) returns (bool success) { 18 | if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value) { 19 | balances[_to] += _value; 20 | balances[_from] -= _value; 21 | allowed[_from][msg.sender] -= _value; 22 | Transfer(_from, _to, _value); 23 | return true; 24 | } else { return false; } 25 | } 26 | 27 | function approve(address _spender, uint256 _value) returns (bool success) { 28 | allowed[msg.sender][_spender] = _value; 29 | Approval(msg.sender, _spender, _value); 30 | return true; 31 | } 32 | 33 | //function approveAndCall() 34 | 35 | function allowance(address _owner, address _spender) constant returns (uint256 remaining) { 36 | return allowed[_owner][_spender]; 37 | } 38 | 39 | function balanceOf(address _owner) constant returns (uint256 balance) { 40 | return balances[_owner]; 41 | } 42 | 43 | event Approval(address indexed _owner, address indexed _spender, uint256 _value); 44 | event Transfer(address indexed _from, address indexed _to, uint256 _value); 45 | } 46 | -------------------------------------------------------------------------------- /CurationMarkets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.10; 2 | 3 | import "./ERC20Token.sol"; 4 | 5 | /* 6 | DO NOT USE. This is a still a WIP. 7 | 8 | Code is MIT licensed. 9 | */ 10 | 11 | /* 12 | Continuous Token is about the minting/withdrawing of the curation market. 13 | It allows tokens to be minted, the ETH kept in a pool, and then withdrawn from supply. 14 | This can be re-used without the bonding functionality. 15 | */ 16 | contract ContinuousToken is ERC20Token { 17 | 18 | uint public constant MAX_UINT = (2**256) - 1; 19 | 20 | uint256 baseCost = 100000000000000; //100000000000000 wei 0.0001 ether 21 | uint256 public costPerToken = 0; 22 | 23 | uint256 public totalEverMinted; 24 | uint256 public totalEverWithdrawn; 25 | uint256 public poolBalance; 26 | 27 | uint8 decimals; 28 | string symbol; 29 | string name; 30 | 31 | function ContinuousToken(uint8 _decimals, string _symbol, string _name) { 32 | decimals = _decimals; 33 | symbol = _symbol; 34 | name = _name; 35 | updateCostOfToken(0); //first pass 36 | } 37 | 38 | // via: http://ethereum.stackexchange.com/questions/10425/is-there-any-efficient-way-to-compute-the-exponentiation-of-a-fraction-and-an-in/10432#10432 39 | // Computes `k * (1+1/q) ^ N`, with precision `p`. The higher 40 | // the precision, the higher the gas cost. It should be 41 | // something around the log of `n`. When `p == n`, the 42 | // precision is absolute (sans possible integer overflows). 43 | // Much smaller values are sufficient to get a great approximation. 44 | function fracExp(uint k, uint q, uint n, uint p) internal returns (uint) { 45 | uint s = 0; 46 | uint N = 1; 47 | uint B = 1; 48 | for (uint i = 0; i < p; ++i){ 49 | s += k * N / B / (q**i); 50 | N = N * (n-i); 51 | B = B * (i+1); 52 | } 53 | return s; 54 | } 55 | 56 | function updateCostOfToken(uint256 _supply) internal { 57 | //from protocol design: 58 | //costOfCoupon = (BaseCost + BaseCost*(1.000001618^AvailableSupply)+BaseCost*AvailableSupply/1000) 59 | //totalSupply == AvailableSupply 60 | costPerToken = baseCost+fracExp(baseCost, 618046, _supply, 2)+baseCost*_supply/1000; 61 | LogCostOfTokenUpdate(costPerToken); 62 | } 63 | 64 | //mint 65 | function mint(uint256 _amountToMint) payable returns (bool) { 66 | //balance of msg.sender increases if paid right amount according to protocol 67 | 68 | if(_amountToMint > 0 && (MAX_UINT - _amountToMint) >= totalSupply && msg.value > 0) { 69 | 70 | uint256 totalMinted = 0; 71 | uint256 totalCost = 0; 72 | //for loop to determine cost at each point. 73 | for(uint i = 0; i < _amountToMint; i+=1) { 74 | if(totalCost + costPerToken <= msg.value) { 75 | totalCost += costPerToken; 76 | totalMinted += 1; 77 | updateCostOfToken((totalSupply+i)); 78 | } else { 79 | break; 80 | } 81 | } 82 | 83 | if(totalCost < msg.value) { //some funds left, not enough for one token. Send back funds 84 | msg.sender.transfer(msg.value - totalCost); 85 | } 86 | 87 | totalEverMinted += totalMinted; 88 | totalSupply += totalMinted; 89 | balances[msg.sender] += totalMinted; 90 | poolBalance += totalCost; 91 | 92 | LogMint(totalMinted, totalCost); 93 | 94 | return true; 95 | } else { 96 | throw; 97 | } 98 | } 99 | 100 | function withdraw(uint256 _amountToWithdraw) returns (bool) { 101 | if(_amountToWithdraw > 0 && balances[msg.sender] >= _amountToWithdraw) { 102 | //determine how much you can leave with. 103 | uint256 reward = _amountToWithdraw * poolBalance/totalSupply; //rounding? 104 | msg.sender.transfer(reward); 105 | balances[msg.sender] -= _amountToWithdraw; 106 | totalSupply -= _amountToWithdraw; 107 | updateCostOfToken(totalSupply); 108 | LogWithdraw(_amountToWithdraw, reward); 109 | return true; 110 | } else { 111 | throw; 112 | } 113 | } 114 | 115 | event LogMint(uint256 amountMinted, uint256 totalCost); 116 | event LogWithdraw(uint256 amountWithdrawn, uint256 reward); 117 | event LogCostOfTokenUpdate(uint256 newCost); 118 | } 119 | 120 | /* 121 | Implements a continuous token that can be bonded to curators and subtopic for curation. 122 | */ 123 | contract CurationToken is ContinuousToken { 124 | 125 | //token holder -> curator -> sub-topic -> amount 126 | mapping (address => mapping (address => mapping(string => uint256))) public bonds; 127 | mapping (address => mapping(string => uint256)) public totalBondsPerCuratorPerSubtopic; 128 | 129 | uint256 public totalBonded = 0; 130 | 131 | //main topic. eg #truffle. Hardcoded. 132 | //sub topics examples = #truffle.features or #truffle.pullrequests 133 | string topic; 134 | 135 | function CurationToken(uint8 _decimals, string _symbol, string _name, string _topic) ContinuousToken(_decimals, _symbol, _name) { 136 | topic = _topic; 137 | } 138 | 139 | function bond(address _curator, string _subtopic, uint256 _amount) returns (bool) { 140 | if(balances[msg.sender] >= _amount) { 141 | bonds[msg.sender][_curator][_subtopic] += _amount; 142 | balances[msg.sender] -= _amount; 143 | totalBonded += _amount; 144 | totalBondsPerCuratorPerSubtopic[_curator][_subtopic] += _amount; 145 | LogBond(msg.sender, _curator, _subtopic, _amount); 146 | return true; 147 | } else { 148 | return false; 149 | } 150 | } 151 | 152 | function withdrawBond(address _curator, string _subtopic, uint256 _amount) returns (bool) { 153 | if(bonds[msg.sender][_curator][_subtopic] >= _amount) { 154 | bonds[msg.sender][_curator][_subtopic] -= _amount; 155 | balances[msg.sender] += _amount; 156 | totalBonded -= _amount; 157 | totalBondsPerCuratorPerSubtopic[_curator][_subtopic] -= _amount; 158 | LogWithdrawBond(msg.sender, _curator, _subtopic, _amount); 159 | return true; 160 | } else { 161 | return false; 162 | } 163 | } 164 | 165 | 166 | event LogBond(address indexed holder, address curator, string subtopic, uint256 amount); 167 | event LogWithdrawBond(address indexed holder, address curator, string subtopic, uint256 amount); 168 | 169 | } 170 | 171 | /* 172 | Back information with full backing in that subtopic 173 | Currently just uses event logs. 174 | Have to build a local DB to filter these events. 175 | No internal storage atm. 176 | */ 177 | contract Curator { 178 | 179 | function back(address _token, string _subtopic, string _info) { 180 | CurationToken token = CurationToken(_token); 181 | LogBacking(msg.sender, _info, token.totalBondsPerCuratorPerSubtopic(msg.sender, _subtopic), token.totalBonded()); 182 | } 183 | 184 | function revoke(address _token, string _subtopic, string _info) { 185 | CurationToken token = CurationToken(_token); 186 | LogRevoke(msg.sender, _info, token.totalBondsPerCuratorPerSubtopic(msg.sender, _subtopic), token.totalBonded()); 187 | } 188 | 189 | event LogBacking(address curator, string info, uint256 bondedAmount, uint256 totalBonded); 190 | event LogRevoke(address curator, string info, uint256 bondedAmount, uint256 totalBonded); 191 | } 192 | --------------------------------------------------------------------------------