Ethereum Is Going To Eat Silicon Valley Alive. Here’s Why.

Originally published on Medium.

Many of the current dominators of technological business perform the same task. They serve as a trusted third party in a marketplace of providers and consumers. The trusted company enforces rules in the community, like how Facebook bans accounts that act outside the terms of service. Usually the same company that enforces the rules owns the service. They act as a trusted arbiter for disputes within the market. Usually, to help everything run smoothly, they provide a reputation system for both consumer and producer that enforces a level of good behaviour.

We can see at a glance how many Silicon Valley heavy-hitters act this way.

AirBnB defines a marketplace of short term room/house/apartment rentals. It is currently worth $30 billion USD and takes a 6-12% fee from consumer bookings, with a 3% service fee for providers..

  • It defines a ruleset where consumers pay on a daily basis, producers can charge certain fees.
  • It provides a website, app and backend that stores these rentals, and allows for consumer search and interaction with those rentals. There is no way to interact with AirBnB via API or as a service, and in this sense it is a closed system.
  • Disputes can arise in situations like the consumer damaging or breaking the rules of the rental. The company holds the user’s funds until the stay is done, in case arbitration is required. In the case of disputes where a refund is found to be warranted, the company provides the refund and penalises the provider.
  • Both consumer and provider can review and provide feedback on the other

Uber definies a marketplace of ride-sharing, where car-owners sell transportation to people wanting to get around an area. It is currently worth $70 billion USD and takes 25% of the fee paid from consumer to producer.

  • It defines a ruleset where consumers pay on a hybrid distance/time basis, with generally fixed rates. These fixed rates have a form of automated collective bargaining (surge pricing). They also manage a consumer/producer reputation system.
  • It provides an app for both producers and consumers, and a backend for connecting the two. This backend is a complex scheduling/resource allocation system that we can only really speculate on the design on. I would speculate that the system seeks a fair allocation of rider to car, in that it seeks to minimise user cost and time, while maximising provider utilisation.
  • Consumers can generally dispute through Uber if they believe their trip to have been poorly executed, for instance if the provider takes an extremely sub-optimal route, or if either party acts in an objectionable way. Uber holds onto funds to be able to act as an arbitrator in consumer-against-producer arbitrage, and punishes consumers in the reputation system for their transgressions (e.g. their card declining, insulting a driver).
  • It provides a reputation system for both driver and rider. Low reputation means that agents won’t be prioritised by the scheduling system.

I would challenge the reader to apply the same thinking to a wide range of existing digital titans – eBay, Steam, Amazon, UberEats, and many more. This is a compelling lens through which to view these companies, because it suggests that a change to how these three pillars of modern technological innovation are achieved could be extremely disruptive – especially if that change allows for the new entities that emerge to out-compete the existing services.

So, thinking about the company structures discussed above, we should ask ourselves where the juicy inefficiencies lie. We have a company defining a market, but how efficient is that market? Well, not very. These markets are restricted by a central authority which harnesses it for its own benefit. Solvable market inefficiencies, as much of the history of Silicon Valley style disruption has shown, is a surefire recipe for explosive adoption.

Firstly, most of these services are charging absolutely exorbitant fees for transactions within the market. A market that was able to do away with these fees would immediately be much cheaper than the existing competitors. The price of the trusted middleman is a substantial weight dragging down market efficiency, as the middle-man consumes a portion of the value for itself.

Secondly, there are many sub-markets within the wider market that are non-competitive, and therefore run sub-optimally. For instance, generally the interfaces to these markets are monopolistic. Uber does not let you roll your own Uber application – you must use theirs. But while the interface does have value, it is fundamentally detached from the value of the service itself. Interface monopolies often allows market definers to act unethically by gatekeeping access to the market. If the Uber app started tracking all of your movements tomorrow, and selling that information to advertisers, you would have no real recourse that wouldn’t deny you access to that market. Alternatively, in a parallel universe where if I disagreed with the ethics of Uber’s interface, I could just make and distribute my own, it creates an entirely new and self-contained space for competition. The same logic can be applied to many sub-tasks within the markets. For instance, the sub-task of generating a navigation route for your Uber to follow is something best left to a trusted oracle service, but the selection and payment of this service could feasibly be based on a system where they bid for work and receive some small fraction of the final price.

Distributed blockchain-based computing platforms, such as Ethereum, are poised to become this disruptive force. Ethereum has a significant first-mover advantage in this area, but really this applies to any platform that can do what Ethereum does. This is a vision of an optimistic future where scaling issues have by-and-large been solved through some means or another, and so we will be assuming that both latency and fees for transactions within the network are reasonable.

Smart contracts allow us to create self-governing marketplaces that remove many of the inefficiencies discussed above. Previously a market being well defined require a central authority that is almost always detrimental to its efficiency. Now, we can define completely transparent markets where the rules are clear and unbreakable. Best of all, nobody owns these markets. They will be entirely public spaces, as this is the most efficient option. Markets that are created, owned, and used for wealth extraction will fundamentally be less competitive than public markets, and so will eventually fall from grace due to this middleman inefficiency. This form of new marketplace has been called a Distributed Platform Cooperative. These cooperatives are related to the idea of a Distributed Autonomous Organisation, although they are not synonymous.

Of course, there may be many business cases where a completely decentralized marketplace isn’t the best option. But for many-to-many digital marketplaces, where the centralized power only fulfils the duties mentioned above, it seems like a compelling possibility that they could remove a now useless weight on the system.

Competitive sub-markets also offer the possibility of reducing redundancy in overlapping systems. For instance, do we really need each reputation systems for each marketplace, as we have currently? Users have their eBay rating, their Uber rating, their AirBnB rating, all connected to a concept of their trustworthiness, but all disconnected from each other. Imagine, alternatively, if we connected reputation to identities that can be carried across markets. This is not to say having one reputation system for all users, but rather that a single user could use one reputation system across multiple services. Having reputation transfer across markets means that new users to markets can show trustworthiness more easily. Instead of requiring some kind of gating mechanism (for instance, Steam requires new users to spend $10 or more before unlocking a range of features) a user can just present evidence from a different market. This means that a user can for instance use their reputation as a reliable seller on one marketplace to immediately receive a level of trust in any other participating market. Transferrable trust in this way brings digital reputation more closely in line with the real-world equivalent. We have singular reputations in the real world that we build on and utilise across our lives, which has a stronger incentive for good behaviour due to the difficulty of creating ‘throw-away’ real identity.

I think there is a compelling case for this new paradigm of Distributed Platform Cooperatives to disrupt and outcompete their centralized competition. When we can create platforms that remove some substantial inefficiency, history would suggest that the competitors do not last well. It also gives a tantalizing glimpse into a world of no gatekeepers to a rich collection of markets that all can enter and participate in freely. It is hoped that these well-lubricated markets would provide fair prices to both consumer and producer. The predatory nature of Silicon Valley pricing, while at times advantageous to the consumer, has had less than desirable impacts to the disempowered providers who have to depend on the whims of a central authority for their survival. Distributed markets create a fertile ground for unionization and increased power to the producer, though it will be interesting to see how consumers respond to this new bargaining relationship.

Mad Maps: A Non-Destructive Terrain Pipeline for Unity

There are so many powerful terrain tools out there, but too often you will find yourself having to choose between procedural generation and a hand-crafted touch. For most terrain assets out there, adding polish means that your pipeline become destructive. If you need to go back and alter procedural elements, you will lose all polish work you have done. And what if one asset does one thing well, but not another? How can you combine the results from multiple sources?

Mad Maps is a powerful, integrated collection of tools to solve all of your Unity terrain pipeline needs. It is an effort to build a terrain pipeline that is non-destructive, extensible, flexible, fast and modular. It’s been battle-tested for the past 2 years in a professional studio environment, used for creating massive open world levels. It can be integrated with existing procedural solutions, allow you to split complex levels up into manageable chunks, and easily modify and reuse areas of a world.

Check out some overview videos below:



This is currently making its way to the Unity Asset Store. Stay tuned!

An Intersection Test for Arbitrary Rectangular Prisms

Have you ever had two arbitrarily rotated and sized rectangular prisms, and wanted to check if they’re intersecting? I know I have! Just an old AABB won’t do the trick, as very snug fitting rectangular prisms need to be detected and dismissed. There are some dastardly configurations (for instance, imagine a very very small rectangular prism sitting just above the surface of a massive and highly skewed rectangular prism) which also need to be sussed out.

It turned out to be a surprisingly tricky problem, and I had to pull a lot of different things from a lot different places together to get it working.

So how does it work? Well first lets think about the problem in 2 dimensions. There’s 3 escalating tests we can run to check if these rotated boxes overlap. The first is to generate two axis-aligned boxes and run a quick AABB check as a broad phase check. The second is to iterate the points of one of the boxes and check the overlap. If there are any points within the box, the box is overlapping. If that is inconclusive, we run the final and most expensive test. First, we pick one of the boxes to define a set of axis in whatever dimensions we’re working with. We basically rotate the whole world in such a way that one box is now perfectly aligned with the axis. Then, we project to each axis. If any of the projections do not overlap, we can guarantee that the boxes do not overlap either.

It’s pretty much a straight shoot up into the third dimension for the first 2 tests. However, for the 3rd, instead of projecting a 1D line from a 2D shape as above, we instead project a 2D shape onto a 2D surface. To do this, we decompose the rotated 3D rectangular prism into its composite triangles.

We can then flatten these triangles against a 2D axis by swizzling their coordinates. We then can do the much simpler test of if a triangle is intersecting an axis aligned rectangle, for each triangle. If any of the triangles succeed, the whole axis succeeds and exits. If all axis succeed, the test is a success and the rectangular prisms absolutely do overlap.

As always let me know if you think I’ve done it wrong, or if there was a simpler way to do this, or if you think I fucked up somewhere.

Get it here.

Automating Tinder.com with JavaScript

As a on-and-off user of this particular form of social masochism, it’s clear that there is an optimal strategy, which is to like absolutely everybody indiscriminately, save your SuperLikes for people who really stand out, and then actually make a judgement on if this is the sort of person you’d be interested in if you do match with them. Of course this strategy suffers from a potential Tragedy of the Commons (although worst case is everyone follows this strategy and matches with everyone else), and requires a premium option (as Likes can’t be a limited resource).

Recently, Tinder released a web version of their site, which got me thinking about ways to automate this pretty simple strategy. I spent about half an hour writing this little script, which does the following:

  • Checks the user for a bio
    • If no bio is found, we either like or dislike, depending on preference.
  • Checks the bio against several positive and negative keywords
    • If a positive keyword is found, we attempt to superlike the user
    • If a negative keyword is found, we dislike the user
  • If no positive or negative keywords are found, we like the user

Pretty simple, pretty easy. Find the JS below. To use, run it in the console of Tinder.com while you’re signed in, and leave it for however long you want. Enjoy your matches! Or getting banned.

Future possible improvements:

  • Move to Chrome/Greasemonkey plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// USER PREFS
var superLikeKeywords = [];
var dislikeKeywords = [ ];
var likeWithNoBio = true;

// TINDER MACRO
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

function waitTime ()
{
return 5000 + Math.random() * 1000;
}

async function likeLoop()
{
var lastbio = "";
var likeCounter = 0;
var dislikeCounter = 0;
var superlikeCounter = 0;
while(true)
{
console.log("Likes: " + likeCounter);
console.log("Dislikes: " + dislikeCounter);
console.log("SuperLikes: " + superlikeCounter);

await sleep(waitTime());

var loadingCircles = document.getElementsByClassName("beacon__circle Pos(a) Bd Bdrs(50%) T(10px) Start(10px) W(80px) H(80px) Animdur(4s) Animic(i) Animtf(l) Bdc($c-beacon-pink) Bgc($c-beacon-pink) Animdel(2s)");
while(loadingCircles.length != 0)
{
await sleep(1000);
}

var profileButtons = document.getElementsByClassName("recCard__openProfile Bdrs(50%) Cur(p) Ta(c) Fl(end)");
if(profileButtons.length == 0)
{
console.log("Couldn't find profileButton");
return;
}
var profileButton = profileButtons[0];
if(profileButton == null)
{
console.log("Couldn't find profileButton");
return;
}

profileButton.click();
await sleep(waitTime());

var allButtons = document.getElementsByClassName("button__text Pos(r) Z(1)");
var dislikeButton = allButtons[0];
var superLikeButton = allButtons[1];
var likeButton = allButtons[2];

if(dislikeButton == null)
{
console.log("Couldn't find like dislikeButton");
return;
}
if(superLikeButton == null)
{
console.log("Couldn't find like superLikeButton");
return;
}
if(likeButton == null)
{
console.log("Couldn't find like button");
return;
}

var bioContainers = document.getElementsByClassName("Py(10px) Px(16px) profileCard__bio Ta(start) Us(t) C($c-secondary) BreakWord Whs(pl)");
if(bioContainers.length == 0)
{
// No bio
if(likeWithNoBio)
{
likeButton.click();
console.log("No bio, liking.");
}
else
{
dislikeButton.click();
console.log("No bio, disliking.");
}
continue;
}

var bio = bioContainers[0].getElementsByTagName("span")[0].innerHTML;
console.log("Profile: " + bio);
bio = bio.toLowerCase();

if(bio != lastbio)
{
var keywordFound = false;
// Check like keywords
for(var i = 0; i < superLikeKeywords.length; ++i)
{
var keyword = superLikeKeywords[i];
//console.log("Checking positive keyword: " + keyword);
if(bio.includes(keyword))
{
console.log("Keyword "" + keyword + "" found! Attempting superlike.");
lastbio = bio;
keywordFound = true;

superLikeButton.click();
superlikeCounter++;

await sleep(waitTime());

var back = document.getElementsByClassName("modalManager D(f) StretchedBox CenterAlign Bgc(#000.68)")[0];
if(back == null)
{
console.log("Back click element not found");
break;
}
back.click();
break;
}
}

// Check dislike keywords
for(var i = 0; i < dislikeKeywords.length; ++i)
{
var keyword = dislikeKeywords[i];
//console.log("Checking negative keyword: " + keyword);
if(bio.includes(keyword))
{
console.log("Negative keyword "" + keyword + "" found, disliking.");
lastbio = bio;
keywordFound = true;
dislikeButton.click();
dislikeCounter++;
break;
}
}

if(keywordFound)
{
continue;
}
}
else
{
console.log("Out of superlikes, so we just give out a regular ol' like");
}

likeButton.click();
likeCounter++;
}
}

likeLoop();