aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne
diff options
context:
space:
mode:
authorTaylor Gerring <taylor.gerring@gmail.com>2015-02-16 21:28:33 +0800
committerTaylor Gerring <taylor.gerring@gmail.com>2015-02-16 21:28:33 +0800
commit702218008ee2b6d708d6b2821cdef80736bb3224 (patch)
treed55ff7ce88187082378e7d8e4c2f3aad14d23b4e /Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne
parent202362d9258335c695eb75f55f4be74a50a1af33 (diff)
downloadgo-tangerine-702218008ee2b6d708d6b2821cdef80736bb3224.tar.gz
go-tangerine-702218008ee2b6d708d6b2821cdef80736bb3224.tar.zst
go-tangerine-702218008ee2b6d708d6b2821cdef80736bb3224.zip
Add versioned dependencies from godep
Diffstat (limited to 'Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne')
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/futarchy.se136
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/heap.se55
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/market.se117
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/subcurrency.se35
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/test.py39
5 files changed, 382 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/futarchy.se b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/futarchy.se
new file mode 100644
index 000000000..0d68622ac
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/futarchy.se
@@ -0,0 +1,136 @@
+# 0: current epoch
+# 1: number of proposals
+# 2: master currency
+# 3: last winning market
+# 4: last txid
+# 5: long-term ema currency units purchased
+# 6: last block when currency units purchased
+# 7: ether allocated to last round
+# 8: last block when currency units claimed
+# 9: ether allocated to current round
+# 1000+: [proposal address, market ID, totprice, totvolume]
+
+init:
+ # We technically have two levels of epoch here. We have
+ # one epoch of 1000, to synchronize with the 1000 epoch
+ # of the market, and then 100 of those epochs make a
+ # meta-epoch (I'll nominate the term "seculum") over
+ # which the futarchy protocol will take place
+ contract.storage[0] = block.number / 1000
+ # The master currency of the futarchy. The futarchy will
+ # assign currency units to whoever the prediction market
+ # thinks will best increase the currency's value
+ master_currency = create('subcurrency.se')
+ contract.storage[2] = master_currency
+code:
+ curepoch = block.number / 1000
+ prevepoch = contract.storage[0]
+ if curepoch > prevepoch:
+ if (curepoch % 100) > 50:
+ # Collect price data
+ # We take an average over 50 subepochs to determine
+ # the price of each asset, weighting by volume to
+ # prevent abuse
+ contract.storage[0] = curepoch
+ i = 0
+ numprop = contract.storage[1]
+ while i < numprop:
+ market = contract.storage[1001 + i * 4]
+ price = call(market, 2)
+ volume = call(market, 3)
+ contract.storage[1002 + i * 4] += price
+ contract.storage[1003 + i * 4] += volume * price
+ i += 1
+ if (curepoch / 100) > (prevepoch / 100):
+ # If we are entering a new seculum, we determine the
+ # market with the highest total average price
+ best = 0
+ bestmarket = 0
+ besti = 0
+ i = 0
+ while i < numprop:
+ curtotprice = contract.storage[1002 + i * 4]
+ curvolume = contract.storage[1002 + i * 4]
+ curavgprice = curtotprice / curvolume
+ if curavgprice > best:
+ best = curavgprice
+ besti = i
+ bestmarket = contract.storage[1003 + i * 4]
+ i += 1
+ # Reset the number of proposals to 0
+ contract.storage[1] = 0
+ # Reward the highest proposal
+ call(contract.storage[2], [best, 10^9, 0], 3)
+ # Record the winning market so we can later appropriately
+ # compensate the participants
+ contract.storage[2] = bestmarket
+ # The amount of ether allocated to the last round
+ contract.storage[7] = contract.storage[9]
+ # The amount of ether allocated to the next round
+ contract.storage[9] = contract.balance / 2
+ # Make a proposal [0, address]
+ if msg.data[0] == 0 and curepoch % 100 < 50:
+ pid = contract.storage[1]
+ market = create('market.se')
+ c1 = create('subcurrency.se')
+ c2 = create('subcurrency.se')
+ call(market, [c1, c2], 2)
+ contract.storage[1000 + pid * 4] = msg.data[1]
+ contract.storage[1001 + pid * 4] = market
+ contract.storage[1] += 1
+ # Claim ether [1, address]
+ # One unit of the first currency in the last round's winning
+ # market entitles you to a quantity of ether that was decided
+ # at the start of that epoch
+ elif msg.data[0] == 1:
+ first_subcurrency = call(contract.storage[2], 3)
+ # We ask the first subcurrency contract what the last transaction was. The
+ # way to make a claim is to send the amount of first currency units that
+ # you wish to claim with, and then immediately call this contract. For security
+ # it makes sense to set up a tx which sends both messages in sequence atomically
+ data = call(first_subcurrency, [], 0, 4)
+ from = data[0]
+ to = data[1]
+ value = data[2]
+ txid = data[3]
+ if txid > contract.storage[4] and to == contract.address:
+ send(to, contract.storage[7] * value / 10^9)
+ contract.storage[4] = txid
+ # Claim second currency [2, address]
+ # One unit of the second currency in the last round's winning
+ # market entitles you to one unit of the futarchy's master
+ # currency
+ elif msg.data[0] == 2:
+ second_subcurrency = call(contract.storage[2], 3)
+ data = call(first_subcurrency, [], 0, 4)
+ from = data[0]
+ to = data[1]
+ value = data[2]
+ txid = data[3]
+ if txid > contract.storage[4] and to == contract.address:
+ call(contract.storage[2], [to, value], 2)
+ contract.storage[4] = txid
+ # Purchase currency for ether (target releasing 10^9 units per seculum)
+ # Price starts off 1 eth for 10^9 units but increases hyperbolically to
+ # limit issuance
+ elif msg.data[0] == 3:
+ pre_ema = contract.storage[5]
+ post_ema = pre_ema + msg.value
+ pre_reserve = 10^18 / (10^9 + pre_ema / 10^9)
+ post_reserve = 10^18 / (10^9 + post_ema / 10^9)
+ call(contract.storage[2], [msg.sender, pre_reserve - post_reserve], 2)
+ last_sold = contract.storage[6]
+ contract.storage[5] = pre_ema * (100000 + last_sold - block.number) + msg.value
+ contract.storage[6] = block.number
+ # Claim all currencies as the ether miner of the current block
+ elif msg.data[0] == 2 and msg.sender == block.coinbase and block.number > contract.storage[8]:
+ i = 0
+ numproposals = contract.storage[1]
+ while i < numproposals:
+ market = contract.storage[1001 + i * 3]
+ fc = call(market, 4)
+ sc = call(market, 5)
+ call(fc, [msg.sender, 1000], 2)
+ call(sc, [msg.sender, 1000], 2)
+ i += 1
+ contract.storage[8] = block.number
diff --git a/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/heap.se b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/heap.se
new file mode 100644
index 000000000..1bc442e6d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/heap.se
@@ -0,0 +1,55 @@
+# 0: size
+# 1-n: elements
+
+init:
+ contract.storage[1000] = msg.sender
+code:
+ # Only owner of the heap is allowed to modify it
+ if contract.storage[1000] != msg.sender:
+ stop
+ # push
+ if msg.data[0] == 0:
+ sz = contract.storage[0]
+ contract.storage[sz + 1] = msg.data[1]
+ k = sz + 1
+ while k > 1:
+ bottom = contract.storage[k]
+ top = contract.storage[k/2]
+ if bottom < top:
+ contract.storage[k] = top
+ contract.storage[k/2] = bottom
+ k /= 2
+ else:
+ k = 0
+ contract.storage[0] = sz + 1
+ # pop
+ elif msg.data[0] == 1:
+ sz = contract.storage[0]
+ if !sz:
+ return(0)
+ prevtop = contract.storage[1]
+ contract.storage[1] = contract.storage[sz]
+ contract.storage[sz] = 0
+ top = contract.storage[1]
+ k = 1
+ while k * 2 < sz:
+ bottom1 = contract.storage[k * 2]
+ bottom2 = contract.storage[k * 2 + 1]
+ if bottom1 < top and (bottom1 < bottom2 or k * 2 + 1 >= sz):
+ contract.storage[k] = bottom1
+ contract.storage[k * 2] = top
+ k = k * 2
+ elif bottom2 < top and bottom2 < bottom1 and k * 2 + 1 < sz:
+ contract.storage[k] = bottom2
+ contract.storage[k * 2 + 1] = top
+ k = k * 2 + 1
+ else:
+ k = sz
+ contract.storage[0] = sz - 1
+ return(prevtop)
+ # top
+ elif msg.data[0] == 2:
+ return(contract.storage[1])
+ # size
+ elif msg.data[0] == 3:
+ return(contract.storage[0])
diff --git a/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/market.se b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/market.se
new file mode 100644
index 000000000..2303a0b60
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/market.se
@@ -0,0 +1,117 @@
+# Creates a decentralized market between any two subcurrencies
+
+# Here, the first subcurrency is the base asset and the second
+# subcurrency is the asset priced against the base asset. Hence,
+# "buying" refers to trading the first for the second, and
+# "selling" refers to trading the second for the first
+
+# storage 0: buy orders
+# storage 1: sell orders
+# storage 1000: first subcurrency
+# storage 1001: last first subcurrency txid
+# storage 2000: second subcurrency
+# storage 2001: last second subcurrency txid
+# storage 3000: current epoch
+# storage 4000: price
+# storage 4001: volume
+
+init:
+ # Heap for buy orders
+ contract.storage[0] = create('heap.se')
+ # Heap for sell orders
+ contract.storage[1] = create('heap.se')
+code:
+ # Initialize with [ first_subcurrency, second_subcurrency ]
+ if !contract.storage[1000]:
+ contract.storage[1000] = msg.data[0] # First subcurrency
+ contract.storage[1001] = -1
+ contract.storage[2000] = msg.data[1] # Second subcurrency
+ contract.storage[2001] = -1
+ contract.storage[3000] = block.number / 1000
+ stop
+ first_subcurrency = contract.storage[1000]
+ second_subcurrency = contract.storage[2000]
+ buy_heap = contract.storage[0]
+ sell_heap = contract.storage[1]
+ # This contract operates in "epochs" of 100 blocks
+ # At the end of each epoch, we process all orders
+ # simultaneously, independent of order. This algorithm
+ # prevents front-running, and generates a profit from
+ # the spread. The profit is permanently kept in the
+ # market (ie. destroyed), making both subcurrencies
+ # more valuable
+
+ # Epoch transition code
+ if contract.storage[3000] < block.number / 100:
+ done = 0
+ volume = 0
+ while !done:
+ # Grab the top buy and sell order from each heap
+ topbuy = call(buy_heap, 1)
+ topsell = call(sell_heap, 1)
+ # An order is recorded in the heap as:
+ # Buys: (2^48 - 1 - price) * 2^208 + units of first currency * 2^160 + from
+ # Sells: price * 2^208 + units of second currency * 2^160 + from
+ buyprice = -(topbuy / 2^208)
+ buyfcvalue = (topbuy / 2^160) % 2^48
+ buyer = topbuy % 2^160
+ sellprice = topsell / 2^208
+ sellscvalue = (topsell / 2^160) % 2^48
+ seller = topsell % 2^160
+ # Heap empty, or no more matching orders
+ if not topbuy or not topsell or buyprice < sellprice:
+ done = 1
+ else:
+ # Add to volume counter
+ volume += buyfcvalue
+ # Calculate how much of the second currency the buyer gets, and
+ # how much of the first currency the seller gets
+ sellfcvalue = sellscvalue / buyprice
+ buyscvalue = buyfcvalue * sellprice
+ # Send the currency units along
+ call(second_subcurrency, [buyer, buyscvalue], 2)
+ call(first_subcurrency, [seller, sellfcvalue], 2)
+ if volume:
+ contract.storage[4000] = (buyprice + sellprice) / 2
+ contract.storage[4001] = volume
+ contract.storage[3000] = block.number / 100
+ # Make buy order [0, price]
+ if msg.data[0] == 0:
+ # We ask the first subcurrency contract what the last transaction was. The
+ # way to make a buy order is to send the amount of first currency units that
+ # you wish to buy with, and then immediately call this contract. For security
+ # it makes sense to set up a tx which sends both messages in sequence atomically
+ data = call(first_subcurrency, [], 0, 4)
+ from = data[0]
+ to = data[1]
+ value = data[2]
+ txid = data[3]
+ price = msg.data[1]
+ if txid > contract.storage[1001] and to == contract.address:
+ contract.storage[1001] = txid
+ # Adds the order to the heap
+ call(buy_heap, [0, -price * 2^208 + (value % 2^48) * 2^160 + from], 2)
+ # Make sell order [1, price]
+ elif msg.data[0] == 1:
+ # Same mechanics as buying
+ data = call(second_subcurrency, [], 0, 4)
+ from = data[0]
+ to = data[1]
+ value = data[2]
+ txid = data[3]
+ price = msg.data[1]
+ if txid > contract.storage[2001] and to == contract.address:
+ contract.storage[2001] = txid
+ call(sell_heap, [0, price * 2^208 + (value % 2^48) * 2^160 + from], 2)
+ # Ask for price
+ elif msg.data[0] == 2:
+ return(contract.storage[4000])
+ # Ask for volume
+ elif msg.data[0] == 3:
+ return(contract.storage[1000])
+ # Ask for first currency
+ elif msg.data[0] == 4:
+ return(contract.storage[2000])
+ # Ask for second currency
+ elif msg.data[0] == 5:
+ return(contract.storage[4001])
diff --git a/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/subcurrency.se b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/subcurrency.se
new file mode 100644
index 000000000..1501beff7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/subcurrency.se
@@ -0,0 +1,35 @@
+# Initialization
+# Admin can issue and delete at will
+init:
+ contract.storage[0] = msg.sender
+code:
+ # If a message with one item is sent, that's a balance query
+ if msg.datasize == 1:
+ addr = msg.data[0]
+ return(contract.storage[addr])
+ # If a message with two items [to, value] are sent, that's a transfer request
+ elif msg.datasize == 2:
+ from = msg.sender
+ fromvalue = contract.storage[from]
+ to = msg.data[0]
+ value = msg.data[1]
+ if fromvalue >= value and value > 0 and to > 4:
+ contract.storage[from] = fromvalue - value
+ contract.storage[to] += value
+ contract.storage[2] = from
+ contract.storage[3] = to
+ contract.storage[4] = value
+ contract.storage[5] += 1
+ return(1)
+ return(0)
+ elif msg.datasize == 3 and msg.sender == contract.storage[0]:
+ # Admin can issue at will by sending a [to, value, 0] message
+ if msg.data[2] == 0:
+ contract.storage[msg.data[0]] += msg.data[1]
+ # Change admin [ newadmin, 0, 1 ]
+ # Set admin to 0 to disable administration
+ elif msg.data[2] == 1:
+ contract.storage[0] = msg.data[0]
+ # Fetch last transaction
+ else:
+ return([contract.storage[2], contract.storage[3], contract.storage[4], contract.storage[5]], 4)
diff --git a/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/test.py b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/test.py
new file mode 100644
index 000000000..301a4a845
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/cyberdyne/test.py
@@ -0,0 +1,39 @@
+from __future__ import print_function
+import pyethereum
+t = pyethereum.tester
+s = t.state()
+# Create currencies
+c1 = s.contract('subcurrency.se')
+print("First currency: %s" % c1)
+c2 = s.contract('subcurrency.se')
+print("First currency: %s" % c2)
+# Allocate units
+s.send(t.k0, c1, 0, [t.a0, 1000, 0])
+s.send(t.k0, c1, 0, [t.a1, 1000, 0])
+s.send(t.k0, c2, 0, [t.a2, 1000000, 0])
+s.send(t.k0, c2, 0, [t.a3, 1000000, 0])
+print("Allocated units")
+# Market
+m = s.contract('market.se')
+s.send(t.k0, m, 0, [c1, c2])
+# Place orders
+s.send(t.k0, c1, 0, [m, 1000])
+s.send(t.k0, m, 0, [0, 1200])
+s.send(t.k1, c1, 0, [m, 1000])
+s.send(t.k1, m, 0, [0, 1400])
+s.send(t.k2, c2, 0, [m, 1000000])
+s.send(t.k2, m, 0, [1, 800])
+s.send(t.k3, c2, 0, [m, 1000000])
+s.send(t.k3, m, 0, [1, 600])
+print("Orders placed")
+# Next epoch and ping
+s.mine(100)
+print("Mined 100")
+s.send(t.k0, m, 0, [])
+print("Updating")
+# Check
+assert s.send(t.k0, c2, 0, [t.a0]) == [800000]
+assert s.send(t.k0, c2, 0, [t.a1]) == [600000]
+assert s.send(t.k0, c1, 0, [t.a2]) == [833]
+assert s.send(t.k0, c1, 0, [t.a3]) == [714]
+print("Balance checks passed")