Building a Prediction Market on Ethereum with Solidity: A Use Case Study

RealmLink
Coinmonks

--

Prediction markets are an increasingly popular use case for blockchain technology. They allow individuals to make predictions on future events and incentivize accurate predictions with rewards. In this article, we will explore how to build a prediction market on Ethereum using Solidity. We will also discuss a real-world use case for a prediction market and provide sample code to help developers get started.

Use Case: Predicting the Outcome of Political Elections

Political elections are a prime use case for prediction markets. They provide an opportunity for individuals to make predictions on the outcome of elections and win rewards for accurate predictions. In addition, prediction markets can provide valuable insights into the sentiment and expectations of the general public.

In this use case, we will build a prediction market for the 2024 United States Presidential Election. The prediction market will allow individuals to make predictions on the winning candidate and will distribute rewards to those who accurately predict the outcome.

Design Considerations

Before diving into the code, it is important to consider the design of the prediction market. Here are some key considerations to keep in mind:

  • Token economy: The prediction market will require a token economy to incentivize accurate predictions. Participants should be able to purchase tokens to make predictions and receive rewards for accurate predictions.
  • Oracle: The prediction market will require an oracle to determine the outcome of the election. The oracle will be responsible for reporting the winning candidate to the smart contract.
  • Scalability: The prediction market should be scalable to accommodate a large number of participants and predictions.
  • Security: The prediction market should be secure to prevent fraud and manipulation.

Smart Contract Implementation

None of the smart contracts in this article have been tested and are not production ready, they are here just to show you how you could implement.

Let’s now dive into the implementation of the prediction market smart contract. The smart contract will implement the following features:

  • The PredictionMarket contract will be the main contract that manages the prediction market.
  • The Token contract will implement the token economy for the prediction market.
  • The Oracle contract will be the oracle that reports the winning candidate to the smart contract.
  • The Prediction struct will store the details of each prediction made by participants.

Here is the Solidity code for the PredictionMarket contract:

pragma solidity 0.8.0;

import "./Token.sol";
import "./Oracle.sol";

contract PredictionMarket {
Token public token;
Oracle public oracle;

struct Prediction {
address participant;
uint amount;
string candidate;
bool redeemed;
}

Prediction[] public predictions;

mapping(address => uint) public balances;

constructor(Token _token, Oracle _oracle) {
token = _token;
oracle = _oracle;
}

function makePrediction(string memory _candidate, uint _amount) public {
require(token.balanceOf(msg.sender) >= _amount);
token.transferFrom(msg.sender, address(this), _amount);
predictions.push(Prediction(msg.sender, _amount, _candidate, false));
}

function redeemRewards(uint _index) public {
require(oracle.getWinner() == predictions[_index].candidate && !predictions[_index].redeemed);
uint reward = predictions[_index].amount * token.getPayout();
balances[predictions[_index].participant] += reward;
token.transfer(predictions[_index].participant, reward);
predictions[_index].redeemed = true;
}

function withdrawTokens() public {
require(balances[msg.sender] > 0);
uint amount = balances[msg.sender];
balances[msg.sender] = 0;
token.transfer(msg.sender, amount);
}
}

The PredictionMarket contract includes the following features:

  • The token variable stores the address of the Token contract.
  • The `oracle variable stores the address of the Oracle contract.
  • The Prediction struct stores the details of each prediction made by participants.
  • The predictions array stores all the predictions made by participants.
  • The balances mapping stores the rewards earned by participants.

The makePrediction function allows participants to make predictions on the winning candidate by specifying the candidate's name and the amount of tokens they want to wager.

The redeemRewards function distributes rewards to participants who accurately predicted the outcome of the election. It checks if the prediction at the given index matches the winning candidate reported by the oracle and has not been redeemed yet. If the prediction is accurate, the function calculates the reward amount and transfers it to the participant's balance.

The withdrawTokens function allows participants to withdraw their rewards.

Here is the Solidity code for the Token contract:

pragma solidity 0.8.0;

contract Token {
string public name;
string public symbol;
uint public totalSupply;
uint public payout;

mapping(address => uint) public balances;

constructor(string memory _name, string memory _symbol, uint _totalSupply, uint _payout) {
name = _name;
symbol = _symbol;
totalSupply = _totalSupply;
payout = _payout;
balances[msg.sender] = _totalSupply;
}

function transfer(address _to, uint _amount) public returns (bool) {
require(_to != address(0));
require(balances[msg.sender] >= _amount);
balances[msg.sender] -= _amount;
balances[_to] += _amount;
return true;
}

function transferFrom(address _from, address _to, uint _amount) public returns (bool) {
require(_to != address(0));
require(balances[_from] >= _amount);
require(allowances[_from][msg.sender] >= _amount);
balances[_from] -= _amount;
balances[_to] += _amount;
allowances[_from][msg.sender] -= _amount;
return true;
}

function approve(address _spender, uint _amount) public returns (bool) {
allowances[msg.sender][_spender] = _amount;
emit Approval(msg.sender, _spender, _amount);
return true;
}

function allowance(address _owner, address _spender) public view returns (uint) {
return allowances[_owner][_spender];
}
}

The Token contract includes the following features:

  • The name, symbol, totalSupply, and payout variables store the name, symbol, total supply, and payout rate of the token.
  • The balances mapping stores the balance of tokens held by each participant.
  • The transfer function allows participants to transfer tokens to another address.
  • The transferFrom function allows participants to transfer tokens on behalf of another participant if allowed by the approve function.
  • The approve function allows participants to approve another address to spend a specified amount of tokens on their behalf.
  • The allowance function returns the amount of tokens approved for spending by a given address.

Here is the Solidity code for the Oracle contract:

pragma solidity 0.8.0;

contract Oracle {
string public winningCandidate;

constructor(string memory _winningCandidate) {
winningCandidate = _winningCandidate;
}

function getWinner() public view returns (string memory) {
return winningCandidate;
}
}

The Oracle contract includes the following features:

  • The winningCandidate variable stores the name of the winning candidate reported bythe oracle.
  • The getWinner function returns the name of the winning candidate.

Finally, here is the Solidity code for the PredictionMarket contract:

pragma solidity 0.8.0;

contract PredictionMarket {
address public token;
address public oracle;
uint public totalTokens;
uint public totalPayout;
uint public winnerIndex;
uint public deadline;

struct Prediction {
string candidateName;
uint tokenAmount;
bool redeemed;
}

Prediction[] public predictions;

mapping(address => uint) public balances;

constructor(address _token, address _oracle, uint _totalTokens, uint _totalPayout, uint _deadline) {
token = _token;
oracle = _oracle;
totalTokens = _totalTokens;
totalPayout = _totalPayout;
deadline = _deadline;
}

function makePrediction(string memory _candidateName, uint _tokenAmount) public {
require(block.timestamp < deadline);
require(Token(token).transferFrom(msg.sender, address(this), _tokenAmount));
predictions.push(Prediction(_candidateName, _tokenAmount, false));
}

function redeemRewards(uint _predictionIndex) public {
require(block.timestamp > deadline);
require(!predictions[_predictionIndex].redeemed);
string memory winner = Oracle(oracle).getWinner();
require(keccak256(bytes(predictions[_predictionIndex].candidateName)) == keccak256(bytes(winner)));
predictions[_predictionIndex].redeemed = true;
uint reward = (predictions[_predictionIndex].tokenAmount * totalPayout) / totalTokens;
balances[msg.sender] += reward;
Token(token).transfer(msg.sender, reward);
}

function withdrawTokens() public {
require(balances[msg.sender] > 0);
Token(token).transfer(msg.sender, balances[msg.sender]);
balances[msg.sender] = 0;
}
}

The PredictionMarket contract includes the following features:

  • The token, oracle, totalTokens, totalPayout, winnerIndex, and deadline variables store the addresses of the ERC-20 token, oracle, total number of tokens in the market, total payout rate, index of the winning candidate, and the deadline for making predictions.
  • The Prediction struct stores the details of each prediction made by participants, including the candidate's name, the amount of tokens wagered, and whether the prediction has been redeemed yet.
  • The predictions array stores all the predictions made by participants.
  • The balances mapping stores the rewards earned by participants.
  • The makePrediction function allows participants to make predictions on the winning candidate by specifying the candidate's name and the amount of tokens they want to wager.
  • The redeemRewards function distributes rewards to participants who accurately predicted the outcome of the election. It checks if the prediction at the given index matches the winning candidate reported by the oracle and has not been redeemed yet. If the prediction is accurate, the function calculates the reward amount and transfers it to the participant's balance.
  • The withdrawTokens function allows participants to withdraw their rewards.

With this implementation, participants can make predictions on the outcome of the election using tokens and earn rewards based on the accuracy of their predictions. The Oracle contract can be updated to report the winning candidate after the election, and the PredictionMarket contract will automatically distribute rewards to participants who made accurate predictions.

Overall, building a prediction market on Ethereum with Solidity can provide a decentralized and transparent way for participants to wager on real-world events and earn rewards based on their predictions. However, it is important to carefully consider the design of the market, including the choice of the oracle and the parameters of the market, to ensure its fairness and accuracy.

In this article, we have covered the basics of building a prediction market on Ethereum using Solidity, including the use of ERC-20 tokens, oracles, and smart contracts. We have also provided a use case study and code snippets to help developers get started with implementing their own prediction markets. With these tools and techniques, developers can create innovative and exciting prediction markets that can benefit both participants and the broader community.

If you liked this check these out!

-Interoperability between games — https://medium.com/p/6648f8aaa275

-Self supportable ecosystems — https://medium.com/p/9eda96d06973

-User made web3 game ecosystems — https://medium.com/p/a069b267c6e0

-Decentralised credit scores — https://medium.com/p/8c0439770fd3

-Solidity Dev Study Group — https://discord.gg/KzbcGmrnfN

-Polygon Alliance — https://www.polygonalliance.com/

-Polygon Alliance Discord — https://discord.gg/kJKPCGQu66

Did you enjoy this article?
Feel like buying me a cup of coffee?
Polygon/Eth/Bsc — 0x4A581E0eaf6b71D05905e8E6014dc0277A1B10ad

New to trading? Try crypto trading bots or copy trading on best crypto exchanges

Join Coinmonks Telegram Channel and Youtube Channel get daily Crypto News

Also, Read

--

--

RealmLink
Coinmonks

Focused on interoperability between MMO RPG games