For the Embiggen Airdrop we loaded OpenRelay with 27 million orders ready for people to fill. But before we could start trying to push those orders into OpenRelay, we had to come up with a list of addresses, generate 0x Orders, and sign them. Here’s how we did it.

Address Discovery

We used Massive to scan the blockchain to find every address that had mined a block, sent a transaction, or received a transaction. This is the majority of Ethereum addresses, however any addresses that received Ether through a contract’s internal transaction or a contract’s suicide and never had any other transactions were not discovered through our process. This gave us a list of 27,405,095 unique addresses that existed on the blockchain as of early May.

The command that we used to compile this list of addresses was:

./massive eth getBlocks ~/.ethereum/geth.ipc | \ ./massive eth getAddresses --no-duplicates > address_list.txt

Note that we used an IPC port to connect to Geth. Running your own Ethereum client is necessary for gathering this quantity of data, and using IPC instead of HTTP reduces the network overhead significantly. Even so, it took several days to compile our list of addresses.

Order Generation

Once we had a list of addresses, we used a Python script to generate a CSV with one row for each address. The CSV specified:

maker - One of 30 different makers. More on this in a minute.

- One of 30 different makers. More on this in a minute. makerTokenAddress - The Embiggen token contract address

- The Embiggen token contract address makerTokenAmount - 30 MBGN, in base units

- 30 MBGN, in base units taker - The address from our list

- The address from our list takerTokenAddress - The NotCoin token contract address

- The NotCoin token contract address takerTokenAmount - “1” - We require 1 unit of NotCoin, so that Embiggen orders can’t be partially claimed.

- “1” - We require 1 unit of NotCoin, so that Embiggen orders can’t be partially claimed. salt - We just used “0” for every order. This is actually significant, and we’ll explain why later.

- We just used “0” for every order. This is actually significant, and we’ll explain why later. expirationUnixTimestampSec - 1546322400 - Midnight, January 1, 2019 - US Central Time.

- 1546322400 - Midnight, January 1, 2019 - US Central Time. makerFee / takerFee - Both 0 - We’re not charging fees for Embiggen

/ - Both 0 - We’re not charging fees for Embiggen feeRecipient - Even though we’re not charging fees, OpenRelay will reject the order if it doesn’t recognize the fee recipient address.

- Even though we’re not charging fees, OpenRelay will reject the order if it doesn’t recognize the fee recipient address. exchangeContractAddress - The 0x Exchange Mainnet Contract, v1.

The only thing left after the CSV is a signature.

Maker Addresses

There are 31 different maker addresses involved in the Embiggen Airdrop. In a later blog post I’ll go into detail about the new order book pruning system we’ve developed, but it gets some efficiencies from having multiple makers. We split our 27 million orders up to be distributed by 30 different addresses.

Every potential Ethereum address maps to one of the 30 different maker addresses. Because the expiration time and salt are the same for every order, and the maker address can be deterministically determined from the taker address, given an address we can calculate the (unsigned) order and order hash.

The 31st maker address is held by what we call the offer maker. When users show up at the airdrop page with an address that wasn’t on the blockchain when we compiled our list of addresses, the dApp posts a request to the offer maker. The offer maker calculates their order hash, and checks to see if that address already has an order in OpenRelay (filled or not). If the user doesn’t have an order in OpenRelay, the offer maker will create one and sign it with the offer maker’s private key.

Order Signing

Once we had our CSV, creating signed orders was just one Massive pipeline away:

massive 0x csv --input = orders.csv | \ massive 0x sign massive 0x sign 0x08409de58f3ad94c5e2c53dbe60ae01be472a820.privkey | massive 0x sign 0x0a65659b64573628ff7f90226b5a8bcbd3abf075.privkey | massive 0x sign 0x18e4ff99ee82f4a38292f1a5d5b2951a5d2a6f2d.privkey | massive 0x sign 0x1c5cffc2875f03fb70883b039f9fce398c3eff14.privkey | massive 0x sign 0x1e3fac0a7785ddb93a5820362ee7b6e4264970ea.privkey | massive 0x sign 0x1f95d54ada369ae6539a1f7da9fdf2631fc64f1c.privkey | massive 0x sign 0x1fdfed482a4952264b2cfa3e4449b82e8380cb15.privkey | massive 0x sign 0x27643cf4963cef83fa034f49f75021ca5361af33.privkey | massive 0x sign 0x35cc62fc18f05eff8f72aa8e8ed31f66d8d45ade.privkey | massive 0x sign 0x4a7c1484cdcd04e419522c1dec2df125c2ecff5f.privkey | massive 0x sign 0x528bb53b5f4b0d87ec9efed82b538115421666e8.privkey | massive 0x sign 0x5876ccf9a8450b9e7ff56d35c66e0ce5599a0993.privkey | massive 0x sign 0x5b848146f269177f5df28bdb25becf346a5f91f5.privkey | massive 0x sign 0x62c911c2a943435553ba24ed0dfde13256d305fa.privkey | massive 0x sign 0x636a7b24694b90b8528dd0083eef9b22d429acfc.privkey | massive 0x sign 0x63dc664254e130f02eeb4f08ea6f67d9e9f60ce4.privkey | massive 0x sign 0x78654d120e892f62bd5a089b2e4cfb46afd33112.privkey | massive 0x sign 0x858107b76077e21351f0a81716cb0d3e096bc877.privkey | massive 0x sign 0xa69d4b62b93a254ac8e646fecac3d745538a12f7.privkey | massive 0x sign 0xae4f09df957977c30a6d5489face8086e26cf6c8.privkey | massive 0x sign 0xbabb517f7ae14c1b5fdfab24b4dfca5da510dae9.privkey | massive 0x sign 0xbdf09525ecebe49b2f57b5d4f070f30cf40bd620.privkey | massive 0x sign 0xc0edb327aef5a8b31640b03352ca89a8ae30595c.privkey | massive 0x sign 0xc2e8eaa82ff4b97c7612b14f36f6a4812ef0f473.privkey | massive 0x sign 0xc9a7c44445952993136edef3671fc24dc8c63c4a.privkey | massive 0x sign 0xe7208c0b33abeda492c42dc996a45cff3b263e59.privkey | massive 0x sign 0xe9246efebe7c4a1205fad958859455180f9f90cb.privkey | massive 0x sign 0xe99618c9f89c60ea92449a91bc1c9f8a52c45f18.privkey | massive 0x sign 0xea2496ab9b7a285b9efe849984bbb90cc7ae4de1.privkey | massive 0x sign 0xf9923780c4967d36fdd1abe03373792bd9cf7863.privkey | gzip > orders.gz

Because we didn’t pass the --replace-on-mismatch flag, Massive will only sign orders where the maker matches the private key. Once an order passed through all 30 pipe stages, one of them would have signed it, and it would be ready to go.

For the sake of security, OpenRelay has a computer specifically dedicated to handling keys, which never connects to the Internet. The CSV was taken to that computer on a flash drive, the orders were generated and signed, and the signed orders were put back on the flash drive to be uploaded later.

Final Thoughts

In the next post, I’ll talk about what we had to do to get all of the orders we just generated and signed uploaded into OpenRelay. If you haven’t claimed your Embiggen from the Embiggen Airdrop, head over to get.embiggen.me to claim some Embiggen. You’ll be helping us test OpenRelay, and thanks to the power of compounding interest, the sooner you claim your Embiggen the more you’ll have over time.