Augur's REP token distribution contract, one of the earliest DeFi applications on Ethereum, compiled in Serpent.
Historical Significance
Augur was Ethereum's first major prediction market protocol, and one of the earliest DeFi applications to launch on mainnet. REP was the governance and reporting token at the heart of the system. This contract handled the initial distribution of all 11 million REP tokens to crowdsale participants. It is one of the most complex Serpent contracts deployed on Ethereum mainnet, and one of the last — Serpent was soon superseded by Solidity as the dominant smart contract language.
Context
Written in Serpent, a Python-like EVM language created by Vitalik Buterin that predated Solidity's dominance. The contract uses Serpent's send() builtin with a 5,000 gas stipend — a value changed to 0 in commit a33ef61 on June 20, 2016, just three days after the compiler commit used to build the deployed bytecode (bc4ce59, June 17, 2016). This confirms the contract was compiled months before its October 2016 deployment, using a cached Serpent install. The source is from augur-core commit d4c095c3b (October 5, 2016). Augur's main augur-core repo is at https://github.com/AugurProject/augur-core.
Token Information
Key Facts
Description
The Augur REP (Reputation) Crowdsale contract distributed 11,000,000 REP tokens to early Augur backers in October 2016. REP holders are responsible for reporting on prediction market outcomes in the Augur protocol. This contract implements a full ERC20 token in Serpent with batch distribution via setSaleDistribution(), a stillCreating() time-lock (15,000 second window from deployment), and a getRidOfDustForLaunch() function callable only from a hardcoded Augur DAO address (0x668Fc8D2004379275357c8D8e2502E19153AdEEe). The token is named "Reputation" (REP) with 18 decimals.
Source Verified
Exact 2,037-byte runtime bytecode match. Source: augur-core commit d4c095c3b. Compiler: ethereum/serpent develop branch at commit bc4ce59 (June 17, 2016). The key to finding the correct compiler version was the send() gas value: bc4ce59 uses 5,000 gas (PUSH2 0x1388), while commit a33ef61 three days later changed it to 0. Sourcify does not support Serpent contracts.
Historian Categories
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
DAO Fork Era
The controversial fork to recover funds from The DAO hack.
Bytecode Overview
Verified Source Available
Source verified through compiler archaeology and exact bytecode matching.
View Verification ProofShow source code (Serpent)
# 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/>.
# Storage of all data associated with reporters
# takes reporterID as key, fxpValue is rep amount
data reporting[2**160]
# owner [account balance is coming from], then spender, e.g. approvedToSpend[owner][spender]
# returns amount spender can spend
data approvedToSpend[2**160][2**160]
# whether the contract has been finished seeding
data seeded
# keeps track of total rep in the system
data totalSupply
# token name for display
data name
# token symbol for display
data symbol
# amount of decimals per unit of rep
data decimals
data creator
data creation
event Transfer(from:address:indexed, to:address:indexed, value:uint256)
event Approval(owner:address:indexed, spender:address:indexed, fxpValue:uint256)
# 18 decimals
macro ONE:
10 ** 18
macro refund():
if(msg.value > 0):
if(!send(msg.sender, msg.value)):
throw()
def init():
self.name = "Reputation"
self.symbol = "REP"
self.decimals = 18
self.creator = msg.sender
self.creation = block.timestamp
def any():
refund()
# Transfer rep
# @return 1 if reputation sent
def transfer(receiver: address, fxpValue: uint256):
senderBalance = self.reporting[msg.sender]
if(senderBalance < fxpValue or !self.seeded or stillCreating()):
throw()
if(!safeToSubtract(self.reporting[msg.sender], fxpValue) or !safeToAdd(self.reporting[receiver], fxpValue)):
throw()
self.reporting[msg.sender] -= fxpValue
self.reporting[receiver] += fxpValue
log(type = Transfer, msg.sender, receiver, fxpValue)
return(1: uint256)
# TransferFrom per token api allowing another contract to withdraw on user's behalf
# fails unless from has authorized sender
# @return 1 if rep sent
def transferFrom(from: address, receiver: address, fxpValue: uint256):
senderBalance = self.reporting[from]
if(senderBalance < fxpValue or fxpValue > self.approvedToSpend[from][msg.sender] or !self.seeded or stillCreating()):
throw()
if(!safeToSubtract(self.reporting[from], fxpValue) or !safeToAdd(self.reporting[receiver], fxpValue)):
throw()
self.approvedToSpend[from][msg.sender] -= fxpValue
self.reporting[from] -= fxpValue
self.reporting[receiver] += fxpValue
log(type = Transfer, from, receiver, fxpValue)
return(1: uint256)
# Allows spender to withdraw from your rep account
def approve(spender: address, amount: uint256):
self.approvedToSpend[msg.sender][spender] = amount
log(type = Approval, msg.sender, spender, amount)
return(1: uint256)
# Sets the initial distribution of rep
def setSaleDistribution(addresses: address[], balances: uint256[]):
i = 0
numberOfAddresses = len(addresses)
if(numberOfAddresses != len(balances)):
throw()
if(self.seeded or !stillCreating()):
throw()
if(msg.sender != self.creator):
throw()
while(i < numberOfAddresses):
if(!self.reporting[addresses[i]] && !self.seeded):
self.reporting[addresses[i]] = balances[i]
self.totalSupply += balances[i]
log(type = Transfer, 0, addresses[i], balances[i])
i += 1
if(self.totalSupply == 11000000 * ONE):
self.seeded = 1
if(self.totalSupply > 11000000 * ONE):
throw()
return(1: uint256)
def getRidOfDustForLaunch():
if(msg.sender != 0x668Fc8D2004379275357c8D8e2502E19153AdEEe):
throw()
if(self.reporting[0x0000000000000000000000000000000000000000]):
self.totalSupply -= self.reporting[0x0000000000000000000000000000000000000000]
self.reporting[0x0000000000000000000000000000000000000000] = 0
return(1)
else:
throw()
# Returns amount spender can withdraw from owner
def allowance(owner: address, spender: address):
return(self.approvedToSpend[owner][spender]: uint256)
def totalSupply():
return(self.totalSupply: uint256)
# @return reputation fxpValue
def balanceOf(address: address):
return(self.reporting[address]: uint256)
def name():
return(self.name: uint256)
def decimals():
return(self.decimals: uint256)
def symbol():
return(self.symbol: uint256)
def getSeeded():
return(self.seeded: uint256)
macro stillCreating():
block.timestamp < (self.creation + 15000)
macro throw():
~jump(2**256)
# safe adders idea pulled from piper merriam's btcrelay audit
macro safeToAdd($a, $b):
(($a + $b) >= $a)
macro safeToSubtract($a, $b):
($b <= $a)External Links
Related contracts
TT
Same eraA fixed-supply token with direct transfers only, deployed July 2016.
0xf78bdd...f9d225July 20, 2016shares
Same eraAn early on-chain corporation contract by cryptonomica.net, representing company shares as ERC-20 tokens with embedded voting — deployed hours before the DAO ha
0x684282...9a33b5July 20, 2016MyToken
Same eraA fixed-supply token with transfers and allowance spending, deployed July 2016.
0x0eb106...9be583July 23, 2016ReplayProtection
Same eraAlex Van de Sande's post-DAO-fork ETH/ETC replay-protection splitter. Routes ether or ERC20 tokens to different recipients depending on which chain it runs on.
0x64668c...456541July 27, 2016BeerCoin
Same eraERC20-style 'I owe you a beer' IOU ledger by Nick Johnson (ENS). Each transfer creates a personal beer debt; obligations are tracked and transferable.
0x74c1e4...48f4acJuly 29, 2016Xi
Same eraDAO-era ERC-20-shaped token, May 2016. Symbol is the Greek capital letter Xi. Fixed cap 15,000; 1 token per 0.001 ETH via buy().
0xbe3dc7...cab9dfJuly 31, 2016