SchellingCoin

Loading...
# SchellingCoin implementation
#
# Stored variables:
#
# 0: last_processed_block
# 1: number of hashes submitted
# 2: value
# 3: quicksort_pairs address
#
# 2^160 + 3x: hash
# 2^160 + 3x + 1: deposit
# 2^160 + 3x + 2: address
# 2^170 + x: value
#
# Transaction types:
#
# [1, sha3([address, value])] -> id: submit hash (only works when block number mod 100 < 50)
#
# [2, id, value]: submit answer (only works when block number mod 100 >= 50)
#
# [3]: balance query
#
# [4]: value query
#
# Parameters:
#
# Epoch length: 100 blocks
# Target savings depletion rate: 0.1% per epoch

init:
    contract.storage[0] = block.number
    contract.storage[3] = create('quicksort_pairs.se')

code:
    HASHES = 2^160    
    VALUES = 2^170
    if block.number / 100 > contract.storage[0] / 100:
        # Sort all hashes
        N = contract.storage[1]
        o = array(N * 2)
        i = 0
        j = 0
        while i < N:
            if contract.storage[VALUES + i]:
                o[j] = contract.storage[VALUES + i]   
                o[j + 1] = i
                j += 2
            i += 1
        values = call(contract.storage[3], o, j, j)

        # Calculate total deposit, refund non-submitters and
        # cleanup

        deposits = array(j / 2)
        addresses = array(j / 2)
        
        i = 0
        total_deposit = 0
        while i < j / 2:
            base_index = HASHES + values[i * 2 + 1] * 3
            deposits[i] = contract.storage[base_index + 1]
            addresses[i] = contract.storage[base_index + 2]
            if contract.storage[VALUES + values[i * 2 + 1]]:
                total_deposit += deposits[i]
            else:
                send(addresses[i], deposits[i] * 999 / 1000)
            i += 1

        inverse_profit_ratio = total_deposit / (contract.balance / 1000) + 1

        # Reward everyone
        i = 0
        running_deposit_sum = 0
        halfway_passed = 0
        while i < j / 2:
            new_deposit_sum = running_deposit_sum + deposits[i]
            if new_deposit_sum > total_deposit / 4 and running_deposit_sum < total_deposit * 3 / 4:
                send(addresses[i], deposits[i] + deposits[i] / inverse_profit_ratio * 2)
            else:
                send(addresses[i], deposits[i] - deposits[i] / inverse_profit_ratio)

            if not halfway_passed and new_deposit_sum > total_deposit / 2:
                contract.storage[2] = contract.storage[VALUES + i]
                halfway_passed = 1
            contract.storage[VALUES + i] = 0
            running_deposit_sum = new_deposit_sum
            i += 1
        contract.storage[0] = block.number
        contract.storage[1] = 0
        
    # Hash submission
    if msg.data[0] == 1:
        if block.number % 100 < 50:
            cur = contract.storage[1]
            pos = HASHES + cur * 3
            contract.storage[pos] = msg.data[1]
            contract.storage[pos + 1] = msg.value
            contract.storage[pos + 2] = msg.sender
            contract.storage[1] = cur + 1
            return(cur)
    # Value submission
    elif msg.data[0] == 2:
        if sha3([msg.sender, msg.data[2]], 2) == contract.storage[HASHES + msg.data[1] * 3]:
            contract.storage[VALUES + msg.data[1]] = msg.data[2]
            return(1)
    # Balance request
    elif msg.data[0] == 3:
        return(contract.balance)
    # Value request
    else:
        return(contract.storage[2])
    

Serpent contract for Ethereum

SchellingCoin implementation in Serpent by Vitalik Buterin.

GitHub

Preferences

Note: Your changes won't be saved, because not Logged-in.

Create your own Contract