Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 274 lines (238 sloc) 11.8 KB
# This software (Augur) allows buying && selling event outcomes in ethereum
# Copyright (C) 2015 Forecast Foundation OU
# This program is free software; you can redistribute it &&/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is free software: you can redistribute it &&/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Any questions please contact joey@augur.net
import branches as BRANCHES
import expiringEvents as EXPEVENTS
import reporting as REPORTING
import makeReports as REPORTS
import penalizationCatchup as CATCHUP
import consensusData as CONSENSUS
inset('refund.se')
# sender/owner, then spender
data amountCanSpend[][]
event Transfer(_from:indexed, _to:indexed, _value, timestamp)
event Approval(_owner:indexed, _spender:indexed, value, timestamp)
# fix sender, tx.origin stuff here
# todo should we check collect fees done or no
# send active reputation
# @return value of reputation sent, 0 if not enough reputation
# error messages otherwise
# -1: "Your reputation account was just created, earn some rep. before you can send to others"
# -2: "Receiving address doesn't exist"
def sendReputation(branch, recver, value):
refund()
# Rep cannot be simultaneously spent (transferred) and used to vote
currentVotePeriod = BRANCHES.getVotePeriod(branch)
# you can't trade if you or the person you're sending to have submitted a report, or at all in the second half of the period [b/c you can messup / cheat w/ reporting by gettin extra claims on fees] and you can't trade in the first half of a period until you've been penalized for reporting wrongly/not reporting
# use a diff. fun. than getReport here
#if(value<=0 || EXPEVENTS.getReport(branch, currentVotePeriod, tx.origin, 0) != 0 || EXPEVENTS.getReport(branch, currentVotePeriod, msg.sender, 0) != 0 || EXPEVENTS.getReport(branch, currentVotePeriod, recver, 0) != 0):
# EXPEVENTS.getNumReportsActual(branch, currentVotePeriod, msg.sender)
# return(0)
lastPeriodPenalized = CONSENSUS.getPenalizedUpTo(branch, msg.sender)
lastPeriod = BRANCHES.getVotePeriod(branch)-1
delta = lastPeriod - lastPeriodPenalized
if(delta > 1):
if(CATCHUP.penalizationCatchup(branch, msg.sender)!=1):
return(0)
# need to check all this for the person it's being sent to as well
if(!CONSENSUS.getRepRedistributionDone(branch, msg.sender)):
return(0)
#if(REPORTS.getRRUpToDate()!=1):
# doIt()
# self.RRDone = true
#if(hasReported(lastPeriod) && periodOver && hasntcollectedfees && residual > periodLength/2):
# CONSENSUS.collectFees(lastPeriod)
# before rep, after rep, balance
# person you're sending to needs rr up to date / done as well
# auto increment vote period if needed
sender = tx.origin
senderIndex = REPORTING.repIDToIndex(branch, sender)
receiverIndex = REPORTING.repIDToIndex(branch, recver)
# if the sender's rep. account doesn't exist, make one, only if in first half of period
if(REPORTING.getReporterID(branch, senderIndex)!=tx.origin):
REPORTING.addReporter(branch, sender)
CONSENSUS.setPenalizedUpTo(branch, tx.origin, (BRANCHES.getVotePeriod(branch)-1))
return(-1)
if(REPORTING.getReporterID(branch, receiverIndex)!=recver):
return(-2)
senderBalance = REPORTING.getRepBalance(branch, sender)
if(senderBalance >= value && value > 0):
if(REPORTING.subtractRep(branch, senderIndex, value) && REPORTING.addRep(branch, receiverIndex, value)):
log(type=Transfer, msg.sender, recver, value, timestamp)
return(value)
else:
return(0)
else:
return(0)
# Transfer dormant rep
# @return value of reputation sent, 0 if not enough reputation
# error messages otherwise
# -1: "Your reputation account was just created, earn some rep. before you can send to others"
# -2: "Receiving address doesn't exist"
# sendDormantRep
def transfer(branch, recver, value):
refund()
currentVotePeriod = BRANCHES.getVotePeriod(branch)
if(value<=0):
return(0)
sender = msg.sender
senderIndex = REPORTING.repIDToIndex(branch, sender)
receiverIndex = REPORTING.repIDToIndex(branch, recver)
# if the sender's rep. account doesn't exist, make one
if(REPORTING.getReporterID(branch, senderIndex)!=msg.sender):
CONSENSUS.setPenalizedUpTo(branch, msg.sender, (BRANCHES.getVotePeriod(branch)-1))
REPORTING.addReporter(branch, sender)
CONSENSUS.setPenalizedUpTo(branch, msg.sender, (BRANCHES.getVotePeriod(branch)-1))
return(-1)
if(REPORTING.getReporterID(branch, receiverIndex)!=recver):
return(-2)
senderBalance = REPORTING.balanceOf(branch, sender)
if(senderBalance >= value && value > 0):
if(REPORTING.subtractDormantRep(branch, senderIndex, value) && REPORTING.addDormantRep(branch, receiverIndex, value)):
log(type=Transfer, msg.sender, recver, value, block.timestamp)
return(value)
else:
return(0)
else:
return(0)
# TransferFrom per token api for dormant rep
# fails unless from has authorized sender
def transferFrom(branch, from, recver, value):
refund()
currentVotePeriod = BRANCHES.getVotePeriod(branch)
if(value<=0):
return(0)
sender = from
senderIndex = REPORTING.repIDToIndex(branch, sender)
receiverIndex = REPORTING.repIDToIndex(branch, recver)
# if the sender's rep. account doesn't exist, make one
if(REPORTING.getReporterID(branch, senderIndex)!=from):
CONSENSUS.setPenalizedUpTo(branch, from, (BRANCHES.getVotePeriod(branch)-1))
REPORTING.addReporter(branch, sender)
CONSENSUS.setPenalizedUpTo(branch, from, (BRANCHES.getVotePeriod(branch)-1))
return(-1)
if(REPORTING.getReporterID(branch, receiverIndex)!=recver):
return(-2)
senderBalance = REPORTING.balanceOf(branch, sender)
if(senderBalance >= value && value > 0 && self.amountCanSpend[from][msg.sender]>=value):
if(REPORTING.subtractDormantRep(branch, senderIndex, value) && REPORTING.addDormantRep(branch, receiverIndex, value)):
self.amountCanSpend[from][msg.sender] -= value
log(type=Transfer, from, recver, value, block.timestamp)
return(value)
else:
return(0)
else:
return(0)
# Allows spender to withdraw from your dormant rep account
def approve(branch, spender, value):
self.amountCanSpend[msg.sender][spender] = value
log(type=Approval, msg.sender, spender, value, block.timestamp)
return(1)
# Returns amount spender can withdraw from owner
def allowance(owner, spender):
return(self.amountCanSpend[owner][spender])
# Convert active rep to dormant rep
# error messages
# -1: not in first half of reporting period
# shouldn't be penalized for dormant rep when converting back to active due to not reporting beyond the dormant penalization
# todo when handling dormant rep stuff:
# if a person reported on a round 2 event, they cannot convert their rep to dormant or send rep until they've finished the resolution process for that round 2 event
# unless this just happened to them last period and they reported correctly then
def convertToDormantRep(branch, value):
refund()
# if not in first half of reporting period
periodLength = BRANCHES.getPeriodLength(branch)
if(!CONSENSUS.getRepRedistributionDone(branch, msg.sender)):
return(0)
residual = block.timestamp % periodLength
if(residual > periodLength/2):
return(-1)
# benny comment:
#```Maybe still have this sort-of variable "power" to it, but REP initially doesn't have "full-power", or REP that hasn't been used to report over the past week has now let it's "power-meter" drop to only 20% earning power (it's kind-of dormant), that then ramps back up to 100% power once it gets used a bit. Could there be an element of this type of time-decay programmed into the REP that's helps incentive? Something like this would make the system more automatic, rather than relying on the user to manually switch "on" or switch "off" the REP. If a user knows, "I better report this week or my REP's power meter goes down to 20% again, and it's gonna take extra effort to get it back to full-power", well that's pretty good incentive to keep the user active, without actually taking it from them.```
if(value<=0):
return(0)
lastPeriodPenalized = CONSENSUS.getPenalizedUpTo(branch, msg.sender)
lastPeriod = BRANCHES.getVotePeriod(branch)-1
delta = lastPeriod - lastPeriodPenalized
if(delta > 1):
if(CATCHUP.penalizationCatchup(branch, msg.sender)!=1):
return(0)
#if(REPORTS.getRRUpToDate()!=1):
# doIt()
#if(hasReported(lastPeriod) && periodOver):
#CONSENSUS.collectFees(lastPeriod)
sender = tx.origin
senderIndex = REPORTING.repIDToIndex(branch, sender)
# if the sender's rep. account doesn't exist, make one
if(REPORTING.getReporterID(branch, senderIndex)!=tx.origin):
REPORTING.addReporter(branch, sender)
CONSENSUS.setPenalizedUpTo(branch, tx.origin, (BRANCHES.getVotePeriod(branch)-1))
return(-1)
senderBalance = REPORTING.getRepBalance(branch, sender)
if(senderBalance >= value):
if(REPORTING.subtractRep(branch, senderIndex, value) && REPORTING.addDormantRep(branch, senderIndex, value)):
REPORTING.adjustActiveRep(branch, -value)
return(value)
else:
return(0)
else:
return(0)
# Convert dormant rep to active rep
# error messages
# -1: not in first half of reporting period
def convertToActiveRep(branch, value):
refund()
# if not in first half of reporting period
periodLength = BRANCHES.getPeriodLength(branch)
residual = block.timestamp % periodLength
if(residual > periodLength/2):
return(-1)
lastPeriodPenalized = CONSENSUS.getPenalizedUpTo(branch, msg.sender)
lastPeriod = BRANCHES.getVotePeriod(branch)-1
delta = lastPeriod - lastPeriodPenalized
if(delta > 1):
if(CATCHUP.penalizationCatchup(branch, msg.sender)!=1):
return(0)
if(!CONSENSUS.getRepRedistributionDone(branch, msg.sender)):
return(0)
if(value<=0):
return(0)
#if(REPORTS.getRRUpToDate()):
#doIt()
#if(hasReported(lastPeriod) && periodOver):
#CONSENSUS.collectFees(lastPeriod)
sender = tx.origin
senderIndex = REPORTING.repIDToIndex(branch, sender)
# if the sender's rep. account doesn't exist, make one
if(REPORTING.getReporterID(branch, senderIndex)!=tx.origin):
REPORTING.addReporter(branch, sender)
CONSENSUS.setPenalizedUpTo(branch, tx.origin, (BRANCHES.getVotePeriod(branch)-1))
return(-1)
senderBalance = REPORTING.balanceOf(branch, sender)
if(senderBalance >= value):
if(REPORTING.subtractDormantRep(branch, senderIndex, value) && REPORTING.addRep(branch, senderIndex, value)):
REPORTING.adjustActiveRep(branch, value)
return(value)
else:
return(0)
else:
return(0)
macro hasReported($branch, $period):
EXPEVENTS.getNumReportsActual($branch, $period, msg.sender)