@sudobility/heavymath_contracts 0.1.21 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -210
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,242 +1,79 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @sudobility/heavymath_contracts
|
|
2
2
|
|
|
3
|
-
Multi-chain prediction market
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Novel Prediction Mechanism**: Predictors specify percentage-based odds instead of binary yes/no
|
|
8
|
-
- **Equilibrium Algorithm**: Automatically determines market sides based on bet distribution
|
|
9
|
-
- **Multi-Chain Support**: Unified TypeScript client for EVM and Solana
|
|
10
|
-
- **UUPS Upgradeable**: Contracts can be upgraded post-deployment for bug fixes and improvements
|
|
11
|
-
- **Oracle Integration**: Chainlink (EVM) and Switchboard (Solana) for result resolution
|
|
12
|
-
- **Dealer NFT System**: NFT-based permissions for creating prediction markets
|
|
13
|
-
- **USDC Settlement**: EVM markets accept ERC20 deposits (USDC by default) with SafeERC20 handling and pre-deadline withdrawals
|
|
14
|
-
- **Safety Valves**: Dealers (or the contract owner) can cancel empty markets, anyone can abandon unresolved markets after a grace period, and the system auto-refunds if equilibrium has no opposing side
|
|
15
|
-
|
|
16
|
-
## Architecture
|
|
17
|
-
|
|
18
|
-
### Smart Contracts
|
|
19
|
-
|
|
20
|
-
**EVM (Ethereum, Polygon, Arbitrum, Base)**:
|
|
21
|
-
- `DealerNFT`: UUPS upgradeable NFT granting market creation permissions
|
|
22
|
-
- `PredictionMarket`: UUPS upgradeable contract managing all prediction markets
|
|
23
|
-
- Requires a configured ERC20 stake token (USDC) during initialization
|
|
24
|
-
- Supports `withdrawPrediction`, `cancelMarket`, and `abandonMarket` flows for safer user refunds
|
|
25
|
-
- Dealer and system fees are accrued and withdrawn in the stake token
|
|
26
|
-
|
|
27
|
-
**Solana** (Coming soon):
|
|
28
|
-
- Anchor programs for NFT and prediction market functionality
|
|
29
|
-
|
|
30
|
-
### TypeScript Client
|
|
31
|
-
|
|
32
|
-
Three-layer architecture:
|
|
33
|
-
- **EVM Client**: Direct interaction with EVM contracts using viem
|
|
34
|
-
- **Solana Client**: Direct interaction with Solana programs
|
|
35
|
-
- **Unified Client**: Chain-agnostic interface working across both chains
|
|
3
|
+
Multi-chain prediction market smart contracts and TypeScript SDK for EVM chains. Features a percentage-based prediction mechanism with equilibrium-based settlement.
|
|
36
4
|
|
|
37
5
|
## Installation
|
|
38
6
|
|
|
39
7
|
```bash
|
|
40
|
-
|
|
8
|
+
bun add @sudobility/heavymath_contracts
|
|
41
9
|
```
|
|
42
10
|
|
|
43
11
|
## Usage
|
|
44
12
|
|
|
45
|
-
### EVM Example
|
|
46
|
-
|
|
47
13
|
```typescript
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import { PredictionClient } from '@heavymath/prediction-contracts';
|
|
51
|
-
|
|
52
|
-
const walletClient = createWalletClient({
|
|
53
|
-
chain: sepolia,
|
|
54
|
-
transport: http()
|
|
55
|
-
});
|
|
14
|
+
import { PredictionClient } from '@sudobility/heavymath_contracts';
|
|
15
|
+
import { EVMPredictionClient } from '@sudobility/heavymath_contracts/evm';
|
|
56
16
|
|
|
57
|
-
const client = new
|
|
58
|
-
predictionMarket:
|
|
59
|
-
stakeToken:
|
|
17
|
+
const client = new EVMPredictionClient({
|
|
18
|
+
predictionMarket: '0x...',
|
|
19
|
+
stakeToken: '0x...', // USDC address (optional, resolved on-chain)
|
|
60
20
|
});
|
|
61
21
|
|
|
62
|
-
//
|
|
63
|
-
await client.
|
|
64
|
-
{ walletClient, publicClient },
|
|
65
|
-
{
|
|
66
|
-
tokenId: 1n,
|
|
67
|
-
category: 1n,
|
|
68
|
-
subCategory: 2n,
|
|
69
|
-
deadline: BigInt(Math.floor(Date.now() / 1000) + 86_400),
|
|
70
|
-
description: "Team A wins",
|
|
71
|
-
oracleId: "0x0000000000000000000000000000000000000000000000000000000000000000"
|
|
72
|
-
}
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
// Place a prediction (handles USDC approval automatically)
|
|
76
|
-
await client.evm.placePrediction(
|
|
77
|
-
{ walletClient, publicClient },
|
|
78
|
-
1n,
|
|
79
|
-
60,
|
|
80
|
-
1_000_000n // 1 USDC (6 decimals)
|
|
81
|
-
);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Development
|
|
85
|
-
|
|
86
|
-
### Setup
|
|
22
|
+
// Place a prediction (auto-approves ERC20)
|
|
23
|
+
await client.placePrediction(walletContext, marketId, 60, 1_000_000n);
|
|
87
24
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
# Edit .env with your configuration
|
|
95
|
-
|
|
96
|
-
# Compile contracts
|
|
97
|
-
npm run compile:evm
|
|
98
|
-
|
|
99
|
-
# Run tests
|
|
100
|
-
npm run test:evm
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### Build
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
# Build all
|
|
107
|
-
npm run build
|
|
25
|
+
// Create a market (requires Dealer NFT)
|
|
26
|
+
await client.createMarket(walletContext, {
|
|
27
|
+
tokenId: 1n, category: 1n, subCategory: 2n,
|
|
28
|
+
deadline: BigInt(Math.floor(Date.now() / 1000) + 86400),
|
|
29
|
+
description: 'Team A wins',
|
|
30
|
+
});
|
|
108
31
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
npm run build:solana # Solana programs + client
|
|
112
|
-
npm run build:unified # Unified client
|
|
32
|
+
// Read market state
|
|
33
|
+
const market = await client.getMarket(publicClient, marketId);
|
|
113
34
|
```
|
|
114
35
|
|
|
115
|
-
|
|
36
|
+
## Smart Contracts
|
|
116
37
|
|
|
117
|
-
|
|
118
|
-
# Run all tests
|
|
119
|
-
npm test
|
|
120
|
-
|
|
121
|
-
# Run specific tests
|
|
122
|
-
npm run test:evm # EVM contract tests
|
|
123
|
-
npm run test:solana # Solana program tests
|
|
124
|
-
npm run test:unified # Unified client tests
|
|
125
|
-
|
|
126
|
-
# Run PredictionClient example (requires env vars)
|
|
127
|
-
PRIVATE_KEY=0x... \
|
|
128
|
-
PREDICTION_MARKET=0x... \
|
|
129
|
-
USDC_ADDRESS=0x... \
|
|
130
|
-
node --loader ts-node/esm examples/evm/prediction-client.ts
|
|
131
|
-
```
|
|
38
|
+
Three UUPS-upgradeable Solidity 0.8.24 contracts:
|
|
132
39
|
|
|
133
|
-
|
|
40
|
+
- **PredictionMarket** -- core market lifecycle (create, predict, resolve, claim)
|
|
41
|
+
- **DealerNFT** -- ERC721 licensing with category/subcategory permissions
|
|
42
|
+
- **OracleResolver** -- oracle registration and data feeds
|
|
134
43
|
|
|
135
|
-
|
|
44
|
+
### How It Works
|
|
136
45
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
npm run verify:evm:sepolia
|
|
46
|
+
1. Dealers create markets with a deadline
|
|
47
|
+
2. Users place predictions at a percentage (0-100) with USDC
|
|
48
|
+
3. At deadline, equilibrium is calculated across the percentage spectrum
|
|
49
|
+
4. Winners (on the correct side of equilibrium) share the losers' stakes proportionally
|
|
50
|
+
5. Fees: dealer fee (0.1-2%) + system fee (10% of dealer fee)
|
|
143
51
|
|
|
144
|
-
|
|
145
|
-
npm run prepare-upgrade:evm # Validate upgrade first
|
|
146
|
-
npm run upgrade:evm:sepolia
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
##### Stake Token & Governance Checklist
|
|
150
|
-
|
|
151
|
-
| Network | USDC Token Address | Notes |
|
|
152
|
-
| -------------- | ---------------------------------------------------- | ---------------------------------- |
|
|
153
|
-
| Ethereum Mainnet | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` | Set contract owner to multisig |
|
|
154
|
-
| Base Mainnet | `0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA` | Confirm Circle native USDC |
|
|
155
|
-
| Arbitrum One | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` | |
|
|
156
|
-
| Sepolia (test) | Deploy MockUSDC or use native test USDC address | Configure `USDC_ADDRESS` env var |
|
|
157
|
-
|
|
158
|
-
Deployment scripts must be provided with `USDC_ADDRESS` and `OWNER_MULTISIG` environment variables so the PredictionMarket initializer receives the correct stake token and ownership is transferred to a multi-sig immediately after deployment.
|
|
159
|
-
|
|
160
|
-
#### Solana
|
|
52
|
+
## Development
|
|
161
53
|
|
|
162
54
|
```bash
|
|
163
|
-
#
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
## Project Structure
|
|
171
|
-
|
|
172
|
-
```
|
|
173
|
-
heavymath_contracts/
|
|
174
|
-
├── contracts/ # Solidity contracts (EVM)
|
|
175
|
-
├── programs/ # Anchor programs (Solana)
|
|
176
|
-
├── src/ # TypeScript clients
|
|
177
|
-
│ ├── evm/ # EVM client
|
|
178
|
-
│ ├── solana/ # Solana client
|
|
179
|
-
│ ├── unified/ # Unified client
|
|
180
|
-
│ └── utils/
|
|
181
|
-
├── test/ # Tests
|
|
182
|
-
├── scripts/ # Deployment scripts
|
|
183
|
-
└── examples/ # Usage examples
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
## How It Works
|
|
187
|
-
|
|
188
|
-
### Prediction Mechanism
|
|
189
|
-
|
|
190
|
-
Unlike traditional binary prediction markets, predictors specify a percentage (0-100) representing their desired odds:
|
|
191
|
-
|
|
192
|
-
- **50%**: Willing to bet at 1:1 odds on either side
|
|
193
|
-
- **25%**: Willing to bet at 1:3 odds (risk 1 to win 3)
|
|
194
|
-
- **75%**: Willing to bet at 3:1 odds (risk 3 to win 1)
|
|
195
|
-
|
|
196
|
-
### Equilibrium Algorithm
|
|
197
|
-
|
|
198
|
-
At the prediction deadline, the system calculates an equilibrium point where:
|
|
199
|
-
```
|
|
200
|
-
total_below_equilibrium / total_above_equilibrium = equilibrium / (100 - equilibrium)
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Predictions below the equilibrium bet on the negative outcome, predictions above bet on the positive outcome. If everyone predicts at the same percentage, all bets are refunded.
|
|
204
|
-
|
|
205
|
-
### Payout
|
|
206
|
-
|
|
207
|
-
Winners share the losers' stakes proportionally:
|
|
208
|
-
```
|
|
209
|
-
payout = stake + (stake / total_winner_side) * total_loser_side - fees
|
|
55
|
+
bun run compile:evm # Compile Solidity
|
|
56
|
+
bun run test:evm # Run Hardhat tests
|
|
57
|
+
bun run build # Build all (evm + unified + react-native TS)
|
|
58
|
+
bun run lint # ESLint check
|
|
59
|
+
bun run typecheck # TypeScript check
|
|
60
|
+
bun run deploy:evm:sepolia # Deploy to Sepolia
|
|
210
61
|
```
|
|
211
62
|
|
|
212
|
-
|
|
213
|
-
- Dealer fee: 0.1% - 2% (dealer sets within bounds)
|
|
214
|
-
- System fee: 10% of dealer fee
|
|
63
|
+
## SDK Entry Points
|
|
215
64
|
|
|
216
|
-
|
|
65
|
+
| Import | Description |
|
|
66
|
+
|--------|-------------|
|
|
67
|
+
| `@sudobility/heavymath_contracts` | Unified PredictionClient |
|
|
68
|
+
| `@sudobility/heavymath_contracts/evm` | EVMPredictionClient (viem) |
|
|
217
69
|
|
|
218
|
-
|
|
219
|
-
- **Withdraw Prediction**: Users can call `withdrawPrediction(marketId)` any time before the deadline to reclaim their entire stake.
|
|
220
|
-
- **Cancellation & Abandonment**: Dealers (or the owner) can `cancelMarket` when no wagers exist, and anyone can call `abandonMarket` after the resolution grace period to trigger full refunds if an oracle or dealer disappears.
|
|
221
|
-
- **Oracle Timestamp Guardrails**: `resolveMarketWithOracle` verifies that oracle data was produced after the prediction deadline, so stale feeds can’t settle markets prematurely.
|
|
70
|
+
## Related Packages
|
|
222
71
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
- Reentrancy protection
|
|
228
|
-
- Oracle timeout mechanism
|
|
229
|
-
- Extensive test coverage (>95%)
|
|
72
|
+
- `@sudobility/heavymath_types` -- shared type definitions
|
|
73
|
+
- `@sudobility/heavymath_indexer_client` -- indexer API client
|
|
74
|
+
- `@sudobility/heavymath_lib` -- business logic hooks
|
|
75
|
+
- `heavymath_app` -- frontend web application
|
|
230
76
|
|
|
231
77
|
## License
|
|
232
78
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
## Contributing
|
|
236
|
-
|
|
237
|
-
Contributions welcome! Please read our contributing guidelines first.
|
|
238
|
-
|
|
239
|
-
## Links
|
|
240
|
-
|
|
241
|
-
- Documentation: [Coming soon]
|
|
242
|
-
- GitHub: [https://github.com/heavymath/heavymath_contracts](https://github.com/heavymath/heavymath_contracts)
|
|
79
|
+
BUSL-1.1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/heavymath_contracts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/unified/src/unified/index.js",
|
|
6
6
|
"types": "dist/unified/src/unified/index.d.ts",
|
|
@@ -135,9 +135,9 @@
|
|
|
135
135
|
"peerDependencies": {
|
|
136
136
|
"@solana/spl-token": ">=0.4.0",
|
|
137
137
|
"@solana/web3.js": ">=1.95.0",
|
|
138
|
-
"@sudobility/configs": "^0.0.
|
|
139
|
-
"@sudobility/heavymath_types": "^0.0.
|
|
140
|
-
"@sudobility/types": "^1.9.
|
|
138
|
+
"@sudobility/configs": "^0.0.67",
|
|
139
|
+
"@sudobility/heavymath_types": "^0.0.10",
|
|
140
|
+
"@sudobility/types": "^1.9.57",
|
|
141
141
|
"@tanstack/react-query": ">=5.0.0",
|
|
142
142
|
"buffer": ">=6.0.0",
|
|
143
143
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -193,9 +193,9 @@
|
|
|
193
193
|
"@solana/spl-token": "^0.4.14",
|
|
194
194
|
"@solana/wallet-adapter-base": "^0.9.27",
|
|
195
195
|
"@solana/web3.js": "^1.98.4",
|
|
196
|
-
"@sudobility/configs": "^0.0.
|
|
197
|
-
"@sudobility/heavymath_types": "^0.0.
|
|
198
|
-
"@sudobility/types": "^1.9.
|
|
196
|
+
"@sudobility/configs": "^0.0.67",
|
|
197
|
+
"@sudobility/heavymath_types": "^0.0.10",
|
|
198
|
+
"@sudobility/types": "^1.9.57",
|
|
199
199
|
"@tanstack/react-query": "^5.90.1",
|
|
200
200
|
"@typechain/ethers-v6": "^0.5.1",
|
|
201
201
|
"@typechain/hardhat": "^9.1.0",
|