Any Ethereum wallet can use BetHorde to place or accept bets. Public key cryptography generates fair random outcomes.

Players bet against Houses, not against BetHorde.


Takes only apply to player winnings:

  • 0% ≤ House take ≤ 10%.
  • Contract take:
    • 1.0%:  Winnings < 0.1ETH
    • 0.5%:  0.1ETH ≤ Winnings < 1ETH
    • 0.2%:  1ETH ≤ Winnings < 5ETH
    • 0.1%:  5ETH ≤ Winnings
  • If a bet is not resolved by a house within 24 hours, any address can force a player win and receive the house take.

Viewing Bets

View Bet button can be used to see details on bets that have not been resolved yet. From this view, bets can also be resolved by houses (or forced if they are over 24 hours old).

Navigation links within bet view move through bets placed against a particular house.


Players select the odds of winning and specify the amount to bet. Player has a 1 / odds chance of winning and winnings equal amount × odds (minus house and contract takes).

The protocol below is used to generate random values:

  1. Houses share public part of RSA key before receiving bets.
  2. Players provide a random value when placing bets.
  3. House signs random value with private part of RSA key.
  4. Public part of RSA key used to verify signature.
  5. Signature is used to generate a random outcome.
See contract for details.

Players place bets by selecting a house and specifying:

  • Amount: how much to bet.
  • Odds: bets have a 1 / odds chance of winning a prize of amount × odds.
    • 2 ≤ odds ≤ 1 million.
    • Amount × odds must not exceed house maximum loss or balance.
  • Randomness: a random hex string to include with the bet.
  • Nonce: must increase with each bet to prevent reuse of winning randomness values.
  • Top up: ETH to add to player account. Bet amount is deducted from player account after this top up is added.

Bet Outcome

Houses have 24 hours to resolve bets by providing a cryptographic signature.

Bets that are not resolved within 24 hours can be forced by any ETH wallet. Forcing is an automatic win for the player. House take on a forced bet goes to the wallet that forced it, instead of the house. It is stored in a house account for that wallet.

Last Low Balance Time

Be cautious of houses with recent last low balance time (houses can 'front-run' winning bets by betting against themselves to run out of funds for accepting bets). Last low balance time records last time house balance was below maximum loss after a bet was placed.

Houses are opened with the following parameters:

  • RSA Modulus: public part of RSA key for randomness.
  • Maximum Loss: maximum that house can lose on one bet.
  • Minimum Bet: minimum bet amount that house accepts.
  • Take: % of winnings that house keeps if player wins.
  • Funding can be added at creation or at later times.

Funding can be added at any time. Withdrawing funds and adjusting parameters can only happen when a house is paused and all bets have been resolved. To prevent houses from pausing to avoid incoming winning bets, a pause only starts 250 blocks after it has been requested.

RSA Keys

Houses decide the outcome of bets by signing a bet randomness value with the private part of a 2048-bit RSA key. Houses provide public part of this key in advance, so that only one signature is valid.

This script can be used to securely generate RSA keys in Python and also includes code for signing with these keys. Bets can be signed by providing the private key to the site, or by directly supplying the signed value.

Public part of generated RSA key needs to be provided to BetHorde, but the private part should be saved and kept secret.

Note: if house does not sign bet within 24 hours, any ETH wallet can force a bet (player win) and claim house take.

House Order

Houses addresses are stored in a list and this site displays the first contract in the list by default. Each time a house resolves a bet, it advances one place towards the front, so the most active houses will be at the front of the list.

Web UI is not needed to interact with BetHorde . A copy of the contract is on Ropsten for development and testing.

Devs can be reached by contacting u/bethorde and donations are welcome.

All code hosted on Github.

Smart contract was extensively tested (test code may be released if there is interest). Web UI might have minor issues. Comments are welcome and users are welcome to create additional UIs for this contract.


Smart contract prevents several forms of cheating:

  • Houses supply bad signatures for bets:
    • Houses commit to RSA keys in advance, so only one signature is valid for a given bet.
  • Players reuse winning randomness values:
    • Player randomness is mixed with a nonce to prevent reuse.
  • Houses pause to avoid receiving incoming winning bets:
    • House pauses only take effect 250 blocks after being initiated, so a house would need to prevent a bet from being mined for 250 blocks to avoid it.
  • Houses bet against themselves to have insufficient balance for incoming winning bets:
    • If a house's balance falls below its max loss when a bet is placed, this is recorded in last low balance time. Players should be cautious with houses that have recently had low balance.
See contract for details and implementation.

Toggle Contract State

  • Bets placed:
  • Houses:
  • Last bet timestamp:
  • Game balance:
  • Sale price:
  • Contract balance:

Player Info

  • Balance:
  • Active bets:
  • Winnings:
  • Last nonce:

House Info

View Modulus

  • Balance:
  • Bet balance:
  • Active bets:
  • Completed bets:
  • Next pause:
  • Max loss:
  • Min bet:
  • Last low balance:
  • Oldest bet: