A prediction market protocol on Ethereum. Users can create prediction markets, purchase ERC-20 tokens representing shares in the possible outcomes, and automatically receive their winnings upon market resolution. Pricing is dynamic and follows the LMSR (Logarithmic Market Scoring Rule). Resolution is performed through a hybrid mechanism that combines on-chain voting with a Chainlink oracle (mocked locally via MockV3Aggregator).
Built with Solidity, Hardhat 3, React, Vite, and Tailwind CSS.
Market creation and voting flow:
- Node.js v22 LTS (pinned via
.nvmrc— Hardhat does not officially support v25) - npm v10 or higher
molteni-algisi/
├── blockchain/ # Solidity smart contracts + Hardhat 3
├── docs/ # Architectural documentation
└── frontend/ # React + Vite + Tailwind CSS
Before running any Hardhat or npm command, from the repository root run:
nvm use # reads .nvmrc and switches to Node.js v22This command must be executed every time you open a new terminal at the repository root, before working on blockchain/ or frontend/.
brew install nvm
mkdir -p ~/.nvm
# Edit your shell configuration file
nano ~/.zshrc
# Append the following lines
export NVM_DIR="$HOME/.nvm"
[ -s "/usr/local/opt/nvm/nvm.sh" ] && \. "/usr/local/opt/nvm/nvm.sh"
[ -s "/usr/local/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/usr/local/opt/nvm/etc/bash_completion.d/nvm"
# Reload the configuration
source ~/.zshrcVerify the installation:
nvm --versioncd blockchain
npm installnpx hardhat compilenpx hardhat testEquivalently, from blockchain/:
npm test # delegates to npx hardhat testHardhat 3 tip: the test runners can be invoked individually with:
npx hardhat test solidity # Solidity tests (Foundry-style) npx hardhat test mocha # TypeScript tests with ethers.js
To test the entire system (smart contracts + frontend) on your machine:
-
Start the Hardhat node. Open a terminal and run:
cd blockchain npx hardhat nodeKeep this terminal open. It will print a list of test accounts, each preloaded with 10,000 ETH along with their private keys.
-
Deploy the contracts. In a second terminal, run the Ignition deployment:
cd blockchain npx hardhat ignition deploy ./ignition/modules/Market.ts --network localhostThis module deploys both contracts required by the dApp:
MarketModule#MarketContract— the prediction market protocolMarketModule#MockV3Aggregator— a mock Chainlink price feed used to resolve oracle-based markets on the local chain (initial answer:2000 * 1e8, decimals:8)
The deployed addresses are written to:
blockchain/ignition/deployments/chain-31337/deployed_addresses.jsonStandalone mock deployment. If you only need to redeploy the Chainlink mock (for instance, to reset its stored price), you can use the dedicated module:
npx hardhat ignition deploy ./ignition/modules/MockOracle.ts --network localhost
-
Install dependencies:
cd frontend npm install -
Configure the environment variables. Create a
frontend/.envfile and add both addresses obtained from the deployment step:VITE_CONTRACT_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 VITE_MOCK_FEED_ADDRESS=0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
VITE_CONTRACT_ADDRESS— address ofMarketContract. Required for any interaction with the protocol.VITE_MOCK_FEED_ADDRESS— address ofMockV3Aggregator. Required to create markets with Chainlink-based resolution and to update the mocked price from the developer panel; without it, only manual (vote-based) markets will work.
Both values can be copied verbatim from
blockchain/ignition/deployments/chain-31337/deployed_addresses.json. -
Start the development server:
npm run dev
The dev server will be available at
http://localhost:5173.
To interact with the local blockchain, MetaMask must be configured properly.
In MetaMask, go to Add network > Add a network manually and enter:
- Network name: Hardhat Local
- RPC URL:
http://127.0.0.1:8545 - Chain ID:
31337 - Currency symbol:
ETH
Note: if MetaMask warns you about "GoChain" or the
ETHsymbol, ignore it and click Save anyway. It is a false positive caused by the test chain ID.
To use the 10,000 ETH preloaded balance:
- Copy a Private Key from the output of
npx hardhat node. - In MetaMask, choose Import account and paste the key.
If, after restarting Hardhat, you see incorrect balances or transactions begin to fail:
- In MetaMask, open Settings > Advanced > Clear activity tab data (also called Reset account).
- This clears the cached nonce history and resyncs the correct balance.
Since markets have a deadline, resolution can be tested without waiting for real time to pass by fast-forwarding the blockchain clock:
# Example: advance time by 2 days (172,800 seconds)
cd blockchain
npx hardhat run -e "async function main() { await network.provider.send('evm_increaseTime', [172800]); await network.provider.send('evm_mine'); } main();" --network localhostAfter running this command, reload the frontend: the market will appear expired, and the voting and resolution phases can be exercised.
npm run build # production build into frontend/dist/
npm run preview # preview the production build
npm run lint # run ESLintArchitectural documentation is available in the docs/ directory.
node_modules/directories are excluded from the repository: runnpm installin bothblockchain/andfrontend/after every clone or after any pull that introduces new dependencies.- Compiled artifacts (
blockchain/artifacts/,blockchain/cache/) are excluded as well: runnpx hardhat compileif they are missing. - Never commit
.envfiles or private keys.
