a newsletter by Molly White
Sign in Subscribe

The FTX trial, day four: The fraud was in the code

The jury got a taste of code review as they examined a falsified "insurance fund" and the infamous FTX → Alameda Research "backdoor".

The FTX trial, day four: The fraud was in the code
audio-thumbnail
The FTX trial, day four: The fraud was in the code
0:00
/0:00

We got our first glance at the FTX codebase on Friday. The prosecution brought out Github screenshots as they questioned cooperating witness Gary Wang, the former CTO of FTX who at various times was responsible for the codebases powering both FTX and Alameda Research. Wang has pleaded guilty to four charges.

Although there is some risk of confusing the jury when presenting them with code snippets, prosecutors had Wang step through what the code is doing in a way that seemed pretty clear to me.a It probably helped that FTX's engineers wrote decently clean code, with descriptive variable names and concise functions, and chose a very human-readable language (Python).

Note to self: if you're going to write code to do fraud, make it messy and unreadable to reduce the chances it's later put in front of a jury as evidence.

Much of the conversation revolved around the allow_negative flag that was introduced to the FTX codebase on August 1, 2019. Wang testified that Sam Bankman-Fried had asked him and Nishad Singh (former FTX engineering director, who has also pleaded guilty) to add the flag. Github screenshots show Singh making a code change to add the column in the database, and adding logic to exempt accounts with the flag from checks that would otherwise determine if they had sufficient funds to withdraw.

From Exhibit GX-617

A later change by Wang himself also exempted accounts with this flag from ever being liquidated.

Github diff. Unchanged code: liquidating = (account.margin_fraction < (account.maintenance_margin_fraction_requirement * Decimal(0.99)))  Added line: ) and not account.allow_negative
From Exhibit GX-611

Prosecutors took this opportunity to point out that practically the same day this change was being made at Bankman-Fried's direction, Bankman-Fried was out on Twitter claiming that "[Alameda's] account is just like everyone else's".

Tweet conversation:  Bitshine @bitshine_ Jul 31, 2019 @SBF_Alameda How are you going to resolve the conflict of interest of running your own derivative exchange, AND actively trading against the market at the same time?  People complain that @CryptoHayes trades against the market, yet FTX and your shop is out there.  SBF @SBF_FTX Jul 31, 2019 Alameda is a liquidity provider on FTX but their account is just like everyone else's.  Alameda's incentive is just for FTX to do as well as possible; by far the dominant factor is helping to make the trading experience as good as possible.  Bitshine @bitshine_ I guess we're just suppose to trust that you wont get preferential treatment on your own platform. Don't get me wrong, as a semi quant trader, I enjoyed your videos and FTX is a step in the right direction. BUT, i think there needs to be a bigger discussion about this issue.
Only the first tweet and Bankman-Fried's reply were included in the government's exhibit, but I think the reply is worth including too. (Tweets)

Wang testified that this allow_negative flag was a special privilege given only to Alameda Research's trading accounts, and a database screenshot also showed the effectively unlimited line of credit that Alameda Research could dip into:

Screenshot of a database query returning one row, with username info@alameda-research.com, and borrow 65,355,999,944
Exhibit GX-644

Wang explained that Alameda had not started out with such a high credit limit, but that periodically the trading firm had run into issues placing trades because they didn't have enough collateral, and Sam Bankman-Fried kept asking him to increase their credit limit to prevent it from happening. According to Wang, the limit was originally set to "a few million dollars", but was then increased to $1 billion. After they ran up against that limit, too, Bankman-Fried asked him to set it to a number so large that they wouldn't likely hit the limit. At that point, Wang set it to around $65 billion.1

Finally, prosecutors questioned Wang about the FTX "insurance fund", which was ostensibly supposed to protect both FTX and its customers from trades that went badly even more quickly than the exchange's risk engine could account for. FTX published the fund's supposed balance on their website, and bragged widely about its existence, including in testimony to U.S. Congress. However, according to Wang, the number shown on the website was falsified.

Tweet: FTX @FTX_Official The 5.25 million FTT we put in our insurance fund in 2019 now makes the fund worth over 100 million USD  Screenshot: Backstop Fund Size: 5,478,274.51613972 USD, 5,250,000.00000000 FTT Last updated: 14/02/2021, 08:05:00
Tweet, exhibit GX-751
AUSA: Is it a real number?

Wang: No.

AUSA: So it's a fake number?

Wang: Yes.

AUSA: Was the real number higher or lower than the fake number?

Wang: Lower.

Code snippets shown to the jury demonstrated how Nishad Singh wrote some code that would update the insurance fund amount by adding to it the daily trading volume, multiplied by a randomish number around 7,500, and dividing it by a billion, thus making it appear as though the website was referencing a real account balance that was fluctuating as the exchange added funds or withdrew from it to cover losses. In reality, it was all made up.

Github diff showing addition of code:  def _get_change()-> Decimal:     daily_volume = current_session().query(func.sum(Trade.size * Trade.price)).filter(         Trade.created_at > datetime.now() - timedelta(days=1)).scalar() or Decimal()         return f2d(numpy.random.normal(7500, 3000))* daily_volume / Decimal('1e9')  @always_run_in_transaction(ro=False) def update_public_insurance_fund():     change = _get_change() sess = current_session() +     public_insurance_fund = Public InsuranceFund.get(sess)  sess.add(Public InsuranceFundChange(public_insurance_fund-public_insurance_fund, size-change))     public_insurance_fund.size += change     sess.commit()
From exhibit GX-600. The falsified account balance change is primarily calculated in line 19.

This is pretty damning. One could possibly explain away an inaccurate number — say, one that was hardcoded into the website and never changed to reflect the true fund balance — by saying that they had   correctly represented it at one point in time and forgot to change it. But it's really hard to come up with a good explanation for why the fund was being incremented by a random fluctuating number that was in no way tied to any actual account balance, besides the obvious: that FTX was trying to present a falsified but convincing number to customers. That would be fraud.

Elsewhere in the code, it's possible to observe that the amount of FTT in the fund was actually represented by a hardcoded value in the user interface, and was not pulling from an external datasource to get a real number.

function InsuranceFundInformation() {   let insuranceFund = useData('/stats/insurance_fund');   let classes = useStyles();   if (!insuranceFund) {     return null;   }   return (     <Card className={classes.card}>       <CardContent>         <Typography variant="h5" gutterBottom>           <Trans>Insurance Fund</Trans>         </Typography>         <Typography>           <Trans>             Size: {{ usdSize: coinSizeFormat.format(insuranceFund.size) }} USD,{' '} {{ fttSize: coinSizeFormat.format(5250000) }} FTT           </Trans>         </Typography>       <Typography>         <Trans>           Last updated: {{ lastUpdated: new Date(insuranceFund.updatedAt).toLocaleString() }}         </Trans>       </Typography>       </CardContent>     </Card>   ); }
From exhibit GX-600. The hardcoded FTT value is in line 64.

This wasn't highlighted to jurors, though, probably because the randomized number is far more damning.

As prosecutors continued to question Wang, he explained that there were repeated incidents in which FTX suffered losses that exceeded the real, smaller amount of assets that had been set aside in an insurance fund. One such example was in 2021, when a trader was able to exploit a bug in FTX's margin system that allowed them to take out a massive position in the MobileCoin cryptocurrency. They were eventually liquidated, and FTX suffered a loss of "several hundred million dollars," according to Wang.

Prosecutors haven't mentioned it, but Sam Bankman-Fried would go on to testify under oath in front of the U.S. Congress in May 2022 that "the insurance fund has paid out a net total of $9.5 million" in the preceding three years, and that "the single biggest daily drawdown from the FTX.com insurance fund was $4.7 million."

They did, however, play a clip from the Odd Lots podcast in which Sam Bankman-Fried lied to interviewer Matt Levine, saying that FTX's risk management engine was so good that they had "never had a day … where there's more money that we lost in blowouts to revenue that we made just from trading fees".

Wang went on to testify that the MobileCoin losses, and other similar losses that exceeded the amounts available in the insurance fund, were "taken on" by Alameda — that is, Alameda took over the account's positions and collateral, effectively absorbing the loss as its own. Wang said that Bankman-Fried reasoned "that FTX's balance sheets are more public than Alameda's balance sheets, that investors have access to FTX's finances but not Alameda's finances."

Indeed, just the previous day we had heard testimony from Paradigm venture capitalist Matt Huang, during which balance sheets were shown to the jury that showed $63 million in estimated trading expenses and $63 million in estimated other expenses for all of 2021 — clearly omitting the "several hundred million dollars" lost to the MobileCoin incident.


The defense team only briefly questioned Wang before the court session ended, but began by suggesting to the jury that he might be saying what the government wants to hear in the hopes of receiving a lighter sentence (he faces a maximum of 50 years in prison, but will likely receive a substantially shorter or even no custodial sentence due to his cooperation). They also tried to offer an alternative explanation for the allow_negative flag: that Alameda was in charge of doing conversions from US dollars to stablecoins, and for a brief period in this transaction they needed to borrow the funds from FTX before returning them in stablecoin form. Why they would need a $65 billion ceiling to do so, however, was not addressed, and seems likely to come up in redirect when court resumes on Tuesday.

Tuesday will also bring the testimony of Caroline Ellison, former Alameda Research CEO and on-and-off girlfriend of Sam Bankman-Fried. She is expected to be a star witness in this case, and the defense team has already teased their "blame Caroline" defense in opening statements.

Footnotes

  1. Admittedly I may not be the best judge of this, coming from the software world.

References

  1. Some have wondered why Wang chose such a seemingly arbitrary number as $65,355,999,994. My best guess is he meant to set it to around $65.535 billion (note the transposed 5 and 3), picking the number 65,535 because it is meaningful in computer science as the largest possible value of an unsigned 16-bit integer. That's just a guess, though, and I can't think of anything better.

Loved this post? Consider signing up for a pay-what-you-want subscription or leaving a tip to support Molly White's work, which is entirely funded by readers like you. You can also check out the store!