The Exchange That Could Not List Itself — JavaScript Bug Hunt

Modelled on BATS Global Markets' own IPO (23 March 2012): BATS listed its shares on its own exchange, and on the day a software bug affected trading in…

  • Language: JavaScript
  • Layer: Backend
  • Difficulty: Medium
  • Concepts: Parsing, Validation
  • Modelled on: BATS Global Markets · 2012
  • Visible tests: ordinary symbols reach their unit; a symbol on a lower bound belongs to that row
  • Reward: 50 XP for a complete fix

Briefing

Modelled on BATS Global Markets' own IPO (23 March 2012): BATS listed its shares on its own exchange, and on the day a software bug affected trading in symbols in the range from A to BFZZZ — a range that included the BATS ticker itself. The company withdrew the IPO the same day.

BATS did not publish the faulty code; this project is a reconstruction of a range-routing mistake of that kind. router.js sends a symbol to the matching unit that owns its alphabetical range, but it scans the table with the wrong comparison and never checks the upper bound.

Fix route so every symbol reaches exactly the unit whose range contains it.

Bug report

BUG-BATS-IPO · Priority: P0 · Reported by: market operations

route(table, symbol) — table rows are { lo, hi, unit }, both bounds INCLUSIVE:

  • the symbol is compared upper-cased, as a plain string
  • return the unit of the row with lo <= symbol <= hi
  • a symbol on a boundary belongs to the row that names it ("BG" -> the row whose lo is "BG"; "A" -> the row whose lo is "A")
  • a symbol that falls in no row returns null — never a neighbouring unit

Observed: symbols equal to a range's lower bound went to the wrong unit (or nowhere), and symbols in an unassigned gap were routed anyway.

Logs

[router] BG -> U1 (expected U2)
[router] A -> null

The code as shipped

src/exchange/router.js (editable)

// Sends each symbol to the matching unit that owns its range.
exports.route = function (table, symbol) {
  var s = String(symbol).toUpperCase();
  for (var i = table.length - 1; i >= 0; i--) {
    if (s > table[i].lo) return table[i].unit;
  }
  return null;
};

Read-only context: src/exchange/partitions.js.

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.