Becoming an Oracle Provider for StarkEx

StarkEx for perpetual trading uses external price feeds, which are given to the system in the oracle price tick transaction. StarkEx for Perpetual supports combining many prices from many Oracles/providers into one single quorum.

This page describes the technical steps that you are required to perform in order to be able to be an Oracle provider for StarkEx for Perpetual.

The documentation here refers to a python script, referred to as public_cli in the below pseudo code, that would be open-sourced by StarkWare soon. In the meantime, if you would like to have it, please contact us.

Step 1: Derive your Stark Key Pair From an Ethereum Key Pair

As detailed in the crypto section, STARK proofs use different hash functions and signatures from Ethereum, and therefore in order to sign on prices for the system you will need to create your private starkKey. A recommended and easy yet secure method to create your starkKeywith your Ethereum key is demonstrated here:

  1. Create an Ethereum signature on the constant string "StarkKeyDerivation" (or 0x537461726b4b657944657269766174696f6e)

  2. Hash (using keccak) r and s signature components to one 256-bit word

  3. Remove the last 5 bits of the resulted number to get the 251-bit stark private key

  4. Derive the stark public key from the stark private key with the relevant CLI function

Example

Using Ganache's default Eth account:
eth_key = 0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d
eth_address = 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
eth_signature =
fd85e77f5bb436eb90a4c3324a02fea6ef766e6ac85bffccb6e1cdc03479e9ac
058e6fb13916131dd4df1911098e2df71d582ab86281bf2553e55571aa99064b
1c
eth_signature_hash = keccak256(r, s) =
0x2f008fa70d291380abafd4a98029ff706940d392b2a30d57c09d49a2447407f2
stark_private_key = last251Bits(ethSignatureHash) =
178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F
stark_key = public_cli(starkPrivateKey) =
0x1895a6a77ae14e7987b9cb51329a5adfb17bd8e7c638f92d6892d76e51cebcf

Step 2: Public StarkKey Added to the On-Chain Configuration

For each assetId, the on-chain contract saves as part of its syntheticConfiguration a list of trusted public keys that are allowed to sign this asset. The oracle's public key must be included in the configuration. Otherwise, the STARK proof will not be able to use its signature.

Since the application is the only party allowed to update the on-chain configuration, this step requires the application's consent.

For security reasons, adding a new public key to the on-chain configuration after the system is already deployed, can happen only after a timelock period (usually a few weeks), to allow users that disapprove of the change to exit.

Step 3: Start Signing Prices

Calculate the hash to sign on

Call the hash function in the CLI with the following fields:

  1. timestamp - 32 bit number (seconds since epoch)

  2. price - 120 bit number, with 18 decimal digits after the decimal point

  3. asset_name (of your choice, per asset. for example "BTCUSD") - 128 bit number

  4. oracle_name (your identity. e.g. "Chain") - 40 bit number

Parameters 3 and 4 should be consistent among all the providers of every Oracle entity (i.e. Chainlink, Maker, etc.) that sign on a specific asset.

The CLI function combines and hashes the parameters as shown here:

timestamp = January 1st, 2020 = hex(1577836800) = 0x5e0be100
price = $11512.34 = hex(11512.34 * (10**18)) = 0x27015cfcb0230820000
asset_name = 128bits(hex("BTCUSD")) = 0x42544355534400000000000000000000
oracle_name = hex("Maker") = 0x4d616b6572
first_number = 0(84-bit) || AssetName (128-bit) || oracleName (40-bit) =
425443555344000000000000000000004d616b6572
second_number = 0(100-bit) || Price(120-bit) || Timestamp (32-bit) =
27015cfcb02308200005e0be100
data_hash = pedersen(first_number, second_number) =
3e4113feb6c403cb0c954e5c09d239bf88fedb075220270f44173ac3cd41858

Sign the hashed message with the sign function

Example

signature = StarkSign(key=stark_private_key, data=data_hash) =
r: 0x6a7a118a6fa508c4f0eb77ea0efbc8d48a64d4a570d93f5c61cd886877cb920
s: 0x6de9006a7bbf610d583d514951c98d15b1a0f6c78846986491d2c8ca049fd55