Thursday, 1 November 2018

Is the new post-money SAFE mathematically sound?

Y-Combinator published a new set of documents for their SAFE, short for "Simple Agreement for Future Equity". The new version takes the document from a pre-money investment to a post-money investment. But for those of you that know neither versions, a SAFE is a legal document signed by the SAFE investor and a startup, so that the startup gets cash to build their product and the investor gets equity in the company. How much equity the SAFE investor gets is not spelled out in numbers but in the form of a set of equations that should compute this number at a later stage. "Later" usually means at the next funding round called Series A, where a larger investor injects more cash into an already working prototype of the product. At the point of Series A, it is much more clear on how the product performs and whether there is a market. The Series A investment usually happens a year after the SAFE investment. The assumption here is that it is fair to both the startup and the SAFE investor to derive the number of SAFE shares only when more information is available. Otherwise, the agreement would have to be based on a lot of guesswork, and if the guess is off by a lot, the startup might have sold their great idea for nothing, or the investor might have bought something worthless.

There are more terms and eventualities defined in the SAFE document, e.g. what happens when the company goes bankrupt before Series A or gets acquired before Series A. Also the document talks about things like Post-Money valuation Cap, and unless you are the startup or the SAFE investor mentioned above, you don't really need to know them to appreciate this blog post. Let's look at the intended case, where a SAFE investors signs the agreement with a startup that later raises a Series A round. This event is defined in the document as Equity Financing event and it has the following implications:

(a) Equity Financing. If there is an Equity Financing before the termination of this Safe, on the initial closing of such Equity Financing, this Safe will automatically convert into the greater of: (1) the number of shares of Standard Preferred Stock equal to the Purchase Amount divided by the lowest price per share of the Standard Preferred Stock; or (2) the number of shares of Safe Preferred Stock equal to the Purchase Amount divided by the Safe Price.
So the SAFE investor gets a bunch of shares, and the document says that he gets the great of two numbers. So,
# You will see later, why I am using the assignment operator ← instead of =
SafeShares ← MAX(PurchaseAmount/LowestStandardPreferredStockPrice, PurchaseAmount/SafePrice)
This expression refers to three terms: PurchaseAmount, LowestStandardPreferredStockPrice and SafePrice. The first is a constant, the second is the share price the Series A investor pays, which is negotiated and derived at independently outside of this agreement, so we treat it as constant as well. The term SafePrice however is also something that we have to compute. We find how to derive it in the Section 2 of the SAFE Agreement, titled 'Definitions':
“Safe Price” means the price per share equal to the Post-Money Valuation Cap divided by the Company Capitalization.
To compute the safe price, we need the Post-Money Valuation Cap and the Company Capitalization. So,
SafePrice ← PostMoneyCap/CompCap
PostMoneyCap is a constant, but CompCap requires another computation. Section 2 also defines:
“Company Capitalization” is calculated as of immediately prior to the Equity Financing and (without double-counting):
  • Includes all shares of Capital Stock issued and outstanding;
  • Includes all Converting Securities;
  • Includes all (i) issued and outstanding Options and (ii) Promised Options;
  • Includes the Unissued Option Pool; and
  • Excludes, notwithstanding the foregoing, any increases to the Unissued Option Pool (except to the extent necessary to cover Promised Options that exceed the Unissued Option Pool) in connection with the Equity Financing.
So it's a bunch of numbers that we add together, and at the end we arrive at the total number of stocks that company will have after Series A closes.
CompCap ← CapitalStock + ConvertingSecurities + AllThingsMentioningOptions
Again, we need to look at the definitions of all the terms to do that computation. Most of them are straight forward, but the "Converting Securities" definition is particularly interesting. It is:
“Converting Securities” includes this Safe and other convertible securities issued by the Company, including but not limited to: (i) other Safes; (ii) convertible promissory notes and other convertible debt instruments; and (iii) convertible securities that have the right to convert into shares of Capital Stock.
Let's assume for simplicity that we only have on SAFE agreement and no others. Then we have:
ConvertingSecurities ← SafeShares
Notice the SafeShares is the same as we had it in the beginning of this post. Remember that we ended up here, because we wanted to compute SafeShares, and to do so we find that we need SafeShares! This legal document contains cyclic definitions!

It's an equation system

So instead of viewing those definitions as a way of deriving the defined from some other numbers, we have to view it as an equation system. While the previous version of the SAFE agreement -- the pre-money one -- also set something like goals, the description of those goals were at the same time a way of computing the numbers for said goals. This new post-money version of the SAFE just sets goals leaving the method of computation undefined.

To make things more complicated, it is possible to hand out multiple SAFE agreements, and now you have a lot of interplay between all those agreements. Here is the full equation system:

SafeShares[i] = MAX(PurchaseAmount[i]/LowestStandardPreferredStockPrice, PurchaseAmount[i]/SafePrice[i])
SafePrice[i] = PostMoneyCap[i]/CompCap
CompCap = CapitalStock + ConvertingSecurities + AllThingsMentioningOptions
ConvertingSecurities = SafeShares[1] + SafeShares[2] + ... + SafeShares[n]
See that all SafeShare equations depend on ConvertingSecurities which in turn depends on all SafeShares.

The most naive way of dealing with this is to set random starting values for SafeShare variables and then iterating on the computation using the definitions as computations. If we are lucky the whole thing converges to a stable solution. For this particular equation set, I found this to be the case most often. I made an interactive calculator for this to verify my gut feeling, and also to be able to play around with scenarios, so I can find the one that would be favourable to me. The box below is powered by CodePen, so go and inspect the code if you like.

See the Pen SAFE funding analyser by clefru (@clefru) on CodePen.

However, a word of warning: At the first glance, it is unclear if this equation system has more than one solution. It is far from obvious what the interplay between all SAFE agreements implicates mathematically. If there are multiple solutions, then it is also unclear who's job it is to give the canonical set of numbers. What if one party doesn't like the set of numbers and takes to court?

The model however has interesting properties, and I assume that YC chose it because of that: Each SAFE investor can compute the minimum amount of ownership received by dividing the PostMoneyCap in his contract by his PurchaseAmount. E.g. a 500k$ investment with a 2M$ post-money cap yields at least 25% of ownership after Series A. Well, and with this minimum guarantee of ownership implied by the equation set is exactly where the problem starts. Take a guaranteed 25% SAFE investment as implied by the numbers above and make 5 investors sign 5 deals. Then you have promised in total 125% ownership to your investors. To the equation set above this means that there is no fixed-point in when iterating on the numbers, and that the shares received for each SAFE holder go to infinity, while the SafePrice converges to 0. What are the legal implications of that? YC has yet to publish a user guide for those new agreements. In the meantime, check your numbers with the SAFE calculator above for sanity. Also do so in your best interest, if you are a founder, as you want to know your dilution when handing out term sheets.

Monday, 15 January 2018

Forcing power saving under my broken DPMS implementation

My monitor, or my X version, or my Xorg drivers, or my KMS kernel, or my xscreensaver version, or my goldfish has a broken DPMS implementation, so that my monitor doesn't turn of when idle. This is a particular waste of energy during the night. Luckily my monitor responds correctly to xset dpms force off when issued twice with a small delay. Using xprintidle-ng, I can work around the problem.

ACTIVATE=$(expr 60 \* 1000 \* 45)  # sleep after 45 mins.
while sleep 60; do
    if [ "$LASTIDLE" -lt "$ACTIVATE" -a "$IDLE" -ge "$ACTIVATE" ]; then
        xset dpms force off
        sleep 10
        xset dpms force off

Wednesday, 24 May 2017

PWD-based privilege separation

I am often tempted to try out a random github project with:

# mkdir random-repo
# cd random-repo
# git clone .
# ./configure && make
# emacs
# make
However that is naive from a security standpoint. Makefiles can do just about everything to your workstation, e.g. steal your e-banking credentials from .config/chrome. So, I want sandboxing. And I want it in a way that fuses nicely with the workflow above.

Basing sandbox activation on my shell current working directory seems to work quite nicely. Consider the following:

# id -nu
# echo $PWD
# pwdjail-mkdir random-repo
# cd random-repo
$ id -nu
$ echo $HOME
$ git clone .
$ ./configure && make
$ cd ..
# echo $PWD
# id -nu
# emacs random-repo/src/
  • I use pwdjail-mkdir instead of mkdir.
  • Entering a subdir beneath /home/clefru/devel/random-repo enters the sandbox
  • Leaving /home/clefru/devel/random-repo leaves the sandbox
In a nutshell, the sandbox concept gets fused with your working directory. I found this to fit nicely with my established working habits, that is chdir-ing into a project directory when doing work there. Let's look at how this works under the hood.

pwdjail-mkdir creates a sandbox user with its home directory set to the directory it has just created. My shell has a hook within chpwd, that when changing into a (sub-)directory of a sandbox user's home directory, the hook spawns a sub-shell via sudo for that sandbox user. The sub-shell also has a hook within chpwd that quits the sub-shell when the sandbox directory is left via another cd. Before quitting though, the sub-shell records the cd target directory and passes it to the outer shell. The outer shell, that is still hanging within its chpwd hook, grabs this target directory and chdirs into it. This completes the illusion that all of this is transparent.

To clean things up, I use pwdjail's version of rm -Ir named pwdjail-rm-Ir, which also removes the sandbox user. Sharing files between the sandbox user and the master user is done by setting a default ACL on the sandbox home directory. I still get mixed file owners if I happen to create files from within the sandbox and create files from the outside, but luckily with Posix ACLs I don't need an explicit step to fix permissions if the other users happens to access a file.

Grab the code from, run pwdjail-setup and you are good to go. I tested this only with zsh, so make sure you have that installed.

Wednesday, 2 March 2016

Tool to enable Wifi sending for Sony's Alpha cameras

Sony's A6000 has a nice feature to allow it to push images via Wifi. The camera however only does so, if it has been paired with Sony's PlayMemories Windows software. That's a one time thing, also the pairing isn't really a pairing that's strongly enforced anywhere. It's just settings truncated GUID, that the camera will broadcast after connecting to the Wifi Hotspot.

One could just grab a Windows device and do the pairing, however I was curios to see if I can cut out this requirement. And I could! I added sony-guid-setter.c to falk0069's sony-pm-alt repository which crafts non-standard USB packages so that the camera thinks it's pairing with PlayMemories. How this is done is documented in the of falk0069's repo.

Thursday, 14 August 2014

Native SSH relay

Google's Native SSH client for Chrome supports connecting to SSH via a websocket/HTTP protocol. I reverse engineered the protocol from the published source and wrote a NodeJS counterpart. This is useful if you don't want to expose your SSH port to the world, but want to hide it behind HTTP/Websockets, possibly using an additional authentication flow in front.