polkamarkets-js 3.2.0 → 3.3.1

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.
Files changed (149) hide show
  1. package/abis/AddAdminToLand.json +1 -0
  2. package/abis/ClaimMerkleRoot.json +1 -0
  3. package/abis/CreateLand.json +1 -0
  4. package/abis/CreateMarkets.json +1 -0
  5. package/abis/DeployContracts.json +1 -0
  6. package/abis/DeployMerkleRewardsDistributor.json +1 -0
  7. package/abis/DeployToken.json +1 -0
  8. package/abis/DeployUSDT.json +1 -0
  9. package/abis/MintTokens.json +1 -0
  10. package/abis/PredictionMarketV3_3.json +1 -0
  11. package/abis/PublishMerkleRoot.json +1 -0
  12. package/abis/ResolveMarket.json +1 -0
  13. package/abis/TradeMarket.json +1 -0
  14. package/abis/USDT.json +1 -0
  15. package/package.json +1 -1
  16. package/script/UpdateMarket.s.sol +56 -0
  17. package/scripts/AddAdminToLand.s.sol +29 -0
  18. package/scripts/ClaimMerkleRoot.s.sol +34 -0
  19. package/scripts/CreateLand.s.sol +28 -0
  20. package/scripts/CreateMarkets.s.sol +71 -0
  21. package/scripts/DeployContracts.s.sol +94 -0
  22. package/scripts/DeployMerkleRewardsDistributor.s.sol +27 -0
  23. package/scripts/DeployToken.s.sol +17 -0
  24. package/scripts/DeployUSDT.s.sol +24 -0
  25. package/scripts/MintTokens.s.sol +21 -0
  26. package/scripts/PublishMerkleRoot.s.sol +50 -0
  27. package/scripts/ResolveMarket.s.sol +23 -0
  28. package/scripts/TradeMarket.s.sol +28 -0
  29. package/scripts/UpdateMarket.s.sol +55 -0
  30. package/src/Application.js +2 -1
  31. package/src/interfaces/index.js +2 -0
  32. package/src/models/PredictionMarketV3Contract.js +5 -1
  33. package/src/models/PredictionMarketV3PlusContract.js +39 -2
  34. package/test/UpdateTest.t.sol +55 -0
  35. package/test/WhaleTest.t.sol +188 -0
  36. package/contracts/PredictionMarketV3_4Bad.sol +0 -1487
  37. package/contracts/PredictionMarketV3_4Good.sol +0 -1508
  38. package/dist/Application.d.ts +0 -201
  39. package/dist/Application.d.ts.map +0 -1
  40. package/dist/Application.js +0 -411
  41. package/dist/Application.js.map +0 -1
  42. package/dist/index.d.ts +0 -7
  43. package/dist/index.d.ts.map +0 -1
  44. package/dist/index.js +0 -16
  45. package/dist/index.js.map +0 -1
  46. package/dist/interfaces/index.d.ts +0 -4
  47. package/dist/interfaces/index.d.ts.map +0 -1
  48. package/dist/interfaces/index.js +0 -22
  49. package/dist/interfaces/index.js.map +0 -1
  50. package/dist/models/AchievementsContract.d.ts +0 -43
  51. package/dist/models/AchievementsContract.d.ts.map +0 -1
  52. package/dist/models/AchievementsContract.js +0 -177
  53. package/dist/models/AchievementsContract.js.map +0 -1
  54. package/dist/models/ArbitrationContract.d.ts +0 -23
  55. package/dist/models/ArbitrationContract.d.ts.map +0 -1
  56. package/dist/models/ArbitrationContract.js +0 -47
  57. package/dist/models/ArbitrationContract.js.map +0 -1
  58. package/dist/models/ArbitrationProxyContract.d.ts +0 -14
  59. package/dist/models/ArbitrationProxyContract.d.ts.map +0 -1
  60. package/dist/models/ArbitrationProxyContract.js +0 -26
  61. package/dist/models/ArbitrationProxyContract.js.map +0 -1
  62. package/dist/models/ERC20Contract.d.ts +0 -50
  63. package/dist/models/ERC20Contract.d.ts.map +0 -1
  64. package/dist/models/ERC20Contract.js +0 -99
  65. package/dist/models/ERC20Contract.js.map +0 -1
  66. package/dist/models/FantasyERC20Contract.d.ts +0 -13
  67. package/dist/models/FantasyERC20Contract.d.ts.map +0 -1
  68. package/dist/models/FantasyERC20Contract.js +0 -43
  69. package/dist/models/FantasyERC20Contract.js.map +0 -1
  70. package/dist/models/IContract.d.ts +0 -57
  71. package/dist/models/IContract.d.ts.map +0 -1
  72. package/dist/models/IContract.js +0 -515
  73. package/dist/models/IContract.js.map +0 -1
  74. package/dist/models/PolkamarketsSmartAccount.d.ts +0 -26
  75. package/dist/models/PolkamarketsSmartAccount.d.ts.map +0 -1
  76. package/dist/models/PolkamarketsSmartAccount.js +0 -100
  77. package/dist/models/PolkamarketsSmartAccount.js.map +0 -1
  78. package/dist/models/PredictionMarketContract.d.ts +0 -113
  79. package/dist/models/PredictionMarketContract.d.ts.map +0 -1
  80. package/dist/models/PredictionMarketContract.js +0 -298
  81. package/dist/models/PredictionMarketContract.js.map +0 -1
  82. package/dist/models/PredictionMarketV2Contract.d.ts +0 -157
  83. package/dist/models/PredictionMarketV2Contract.d.ts.map +0 -1
  84. package/dist/models/PredictionMarketV2Contract.js +0 -431
  85. package/dist/models/PredictionMarketV2Contract.js.map +0 -1
  86. package/dist/models/PredictionMarketV3Contract.d.ts +0 -42
  87. package/dist/models/PredictionMarketV3Contract.d.ts.map +0 -1
  88. package/dist/models/PredictionMarketV3Contract.js +0 -277
  89. package/dist/models/PredictionMarketV3Contract.js.map +0 -1
  90. package/dist/models/PredictionMarketV3ControllerContract.d.ts +0 -128
  91. package/dist/models/PredictionMarketV3ControllerContract.d.ts.map +0 -1
  92. package/dist/models/PredictionMarketV3ControllerContract.js +0 -174
  93. package/dist/models/PredictionMarketV3ControllerContract.js.map +0 -1
  94. package/dist/models/PredictionMarketV3FactoryContract.d.ts +0 -31
  95. package/dist/models/PredictionMarketV3FactoryContract.d.ts.map +0 -1
  96. package/dist/models/PredictionMarketV3FactoryContract.js +0 -81
  97. package/dist/models/PredictionMarketV3FactoryContract.js.map +0 -1
  98. package/dist/models/PredictionMarketV3ManagerContract.d.ts +0 -67
  99. package/dist/models/PredictionMarketV3ManagerContract.d.ts.map +0 -1
  100. package/dist/models/PredictionMarketV3ManagerContract.js +0 -97
  101. package/dist/models/PredictionMarketV3ManagerContract.js.map +0 -1
  102. package/dist/models/PredictionMarketV3QuerierContract.d.ts +0 -33
  103. package/dist/models/PredictionMarketV3QuerierContract.d.ts.map +0 -1
  104. package/dist/models/PredictionMarketV3QuerierContract.js +0 -61
  105. package/dist/models/PredictionMarketV3QuerierContract.js.map +0 -1
  106. package/dist/models/PredictionMarketV3_2Contract.d.ts +0 -32
  107. package/dist/models/PredictionMarketV3_2Contract.d.ts.map +0 -1
  108. package/dist/models/PredictionMarketV3_2Contract.js +0 -169
  109. package/dist/models/PredictionMarketV3_2Contract.js.map +0 -1
  110. package/dist/models/RealitioERC20Contract.d.ts +0 -16
  111. package/dist/models/RealitioERC20Contract.d.ts.map +0 -1
  112. package/dist/models/RealitioERC20Contract.js +0 -18
  113. package/dist/models/RealitioERC20Contract.js.map +0 -1
  114. package/dist/models/VotingContract.d.ts +0 -38
  115. package/dist/models/VotingContract.d.ts.map +0 -1
  116. package/dist/models/VotingContract.js +0 -85
  117. package/dist/models/VotingContract.js.map +0 -1
  118. package/dist/models/WETH9Contract.d.ts +0 -29
  119. package/dist/models/WETH9Contract.d.ts.map +0 -1
  120. package/dist/models/WETH9Contract.js +0 -44
  121. package/dist/models/WETH9Contract.js.map +0 -1
  122. package/dist/models/index.d.ts +0 -18
  123. package/dist/models/index.d.ts.map +0 -1
  124. package/dist/models/index.js +0 -37
  125. package/dist/models/index.js.map +0 -1
  126. package/dist/types/contracts.d.ts +0 -46
  127. package/dist/types/contracts.d.ts.map +0 -1
  128. package/dist/types/contracts.js +0 -3
  129. package/dist/types/contracts.js.map +0 -1
  130. package/dist/types/index.d.ts +0 -1
  131. package/dist/types/index.d.ts.map +0 -1
  132. package/dist/types/index.js +0 -3
  133. package/dist/types/index.js.map +0 -1
  134. package/dist/utils/Account.d.ts +0 -34
  135. package/dist/utils/Account.d.ts.map +0 -1
  136. package/dist/utils/Account.js +0 -38
  137. package/dist/utils/Account.js.map +0 -1
  138. package/dist/utils/Contract.d.ts +0 -31
  139. package/dist/utils/Contract.d.ts.map +0 -1
  140. package/dist/utils/Contract.js +0 -123
  141. package/dist/utils/Contract.js.map +0 -1
  142. package/dist/utils/Numbers.d.ts +0 -27
  143. package/dist/utils/Numbers.d.ts.map +0 -1
  144. package/dist/utils/Numbers.js +0 -87
  145. package/dist/utils/Numbers.js.map +0 -1
  146. package/script/CreateMarketLib.sol +0 -1873
  147. package/script/DeployProxy.s.sol +0 -27
  148. package/script/DeployUpgradeablePM.s.sol +0 -47
  149. package/script/PredictionMarketV3_3Flow.s.sol +0 -132
@@ -1,1508 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.26;
3
-
4
- // openzeppelin upgradeable imports
5
- import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
6
- import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
7
- import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
8
- import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
9
-
10
- // openzeppelin non-upgradeable imports (for interfaces)
11
- import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
12
- import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
13
-
14
- // local imports
15
- import "./IFantasyERC20.sol";
16
- import "./IRealityETH_ERC20.sol";
17
- import "./IPredictionMarketV3Manager.sol";
18
- import "./IWETH.sol";
19
-
20
- library CeilDivGood {
21
- // calculates ceil(x/y)
22
- function ceildiv(uint256 x, uint256 y) internal pure returns (uint256) {
23
- if (x > 0) return ((x - 1) / y) + 1;
24
- return 0;
25
- }
26
- }
27
-
28
- /// @title Market Contract Factory
29
- contract PredictionMarketV3_4Good is Initializable, ReentrancyGuardUpgradeable, OwnableUpgradeable, UUPSUpgradeable {
30
- using SafeERC20 for IERC20;
31
- using CeilDivGood for uint256;
32
-
33
- // ------ Events ------
34
-
35
- event MarketCreated(
36
- address indexed user,
37
- uint256 indexed marketId,
38
- uint256 outcomes,
39
- string question,
40
- string image,
41
- IERC20 token
42
- );
43
-
44
- event MarketActionTx(
45
- address indexed user,
46
- MarketAction indexed action,
47
- uint256 indexed marketId,
48
- uint256 outcomeId,
49
- uint256 shares,
50
- uint256 value,
51
- uint256 timestamp
52
- );
53
-
54
- event Referral(
55
- address indexed user,
56
- uint256 indexed marketId,
57
- string code,
58
- MarketAction action,
59
- uint256 outcomeId,
60
- uint256 value,
61
- uint256 timestamp
62
- );
63
-
64
- event MarketOutcomeShares(uint256 indexed marketId, uint256 timestamp, uint256[] outcomeShares, uint256 liquidity);
65
-
66
- event MarketOutcomePrice(uint256 indexed marketId, uint256 indexed outcomeId, uint256 value, uint256 timestamp);
67
-
68
- event MarketLiquidity(
69
- uint256 indexed marketId,
70
- uint256 value, // total liquidity
71
- uint256 price, // value of one liquidity share; max: 1 (even odds situation)
72
- uint256 timestamp
73
- );
74
-
75
- event MarketResolved(
76
- address indexed user,
77
- uint256 indexed marketId,
78
- uint256 outcomeId,
79
- uint256 timestamp,
80
- bool admin
81
- );
82
-
83
- event MarketPaused(address indexed user, uint256 indexed marketId, bool paused, uint256 timestamp);
84
-
85
- event MarketCloseDateEdited(
86
- address indexed user,
87
- uint256 indexed marketId,
88
- uint256 closesAtTimestamp,
89
- uint256 timestamp
90
- );
91
-
92
- event AllowedManagerSet(address indexed manager, bool allowed);
93
-
94
- event Paused(bool paused, address indexed user);
95
-
96
- // ------ Events End ------
97
-
98
- uint256 private constant MAX_UINT_256 = type(uint256).max;
99
-
100
- uint256 private constant ONE = 10**18;
101
-
102
- uint256 public constant MAX_OUTCOMES = 2**5;
103
-
104
- uint256 public constant MAX_FEE = 5 * 10**16; // 5%
105
-
106
- uint256 public constant MINIMUM_REALITIO_TIMEOUT = 3600; // 1 hour
107
-
108
- enum MarketState {
109
- open,
110
- closed,
111
- resolved
112
- }
113
- enum MarketAction {
114
- buy,
115
- sell,
116
- addLiquidity,
117
- removeLiquidity,
118
- claimWinnings,
119
- claimLiquidity,
120
- claimFees,
121
- claimVoided
122
- }
123
-
124
- struct Market {
125
- // market details
126
- uint256 closesAtTimestamp;
127
- uint256 balance; // total stake
128
- uint256 liquidity; // stake held
129
- uint256 sharesAvailable; // shares held (all outcomes)
130
- mapping(address user => uint256 shares) liquidityShares;
131
- mapping(address user => bool claimed) liquidityClaims; // wether user has claimed liquidity earnings
132
- MarketState state; // resolution variables
133
- MarketResolution resolution; // fees
134
- MarketFees fees;
135
- // market outcomes
136
- uint256 outcomeCount;
137
- mapping(uint256 outcomeId => MarketOutcome outcome) outcomes;
138
- IERC20 token; // ERC20 token market will use for trading
139
- IPredictionMarketV3Manager manager; // manager contract
140
- address creator; // market creator
141
- bool paused; // market paused, no trading allowed
142
- }
143
-
144
- struct Fees {
145
- uint256 fee; // fee % taken from every transaction
146
- uint256 treasuryFee; // fee % taken from every transaction to a treasury address
147
- uint256 distributorFee; // fee % taken from every transaction to a distributor address
148
- }
149
-
150
- struct MarketFees {
151
- uint256 poolWeight; // internal var used to ensure pro-rate fee distribution
152
- mapping(address user => uint256 claimed) claimed;
153
- address treasury; // address to send treasury fees to
154
- address distributor; // fee % taken from every transaction to a treasury address
155
- Fees buyFees; // fees for buy transactions
156
- Fees sellFees; // fees for sell transactions
157
- }
158
-
159
- struct MarketResolution {
160
- bool resolved;
161
- IRealityETH_ERC20 realitio;
162
- uint256 outcomeId;
163
- bytes32 questionId; // realitio questionId
164
- // realitio
165
- uint256 realitioTimeout;
166
- }
167
-
168
- struct MarketOutcome {
169
- uint256 marketId;
170
- uint256 id;
171
- Shares shares;
172
- }
173
-
174
- struct Shares {
175
- uint256 total; // number of shares
176
- uint256 available; // available shares
177
- mapping(address user => uint256 shares) holders;
178
- mapping(address user => bool winningsClaimed) claims; // wether user has claimed winnings
179
- mapping(address user => bool voidedClaimed) voidedClaims; // wether user has claimed voided market shares
180
- }
181
-
182
- struct CreateMarketDescription {
183
- uint256 value;
184
- uint32 closesAt;
185
- uint256 outcomes;
186
- IERC20 token;
187
- uint256[] distribution;
188
- string question;
189
- string image;
190
- address arbitrator;
191
- Fees buyFees;
192
- Fees sellFees;
193
- address treasury;
194
- address distributor;
195
- uint32 realitioTimeout;
196
- IPredictionMarketV3Manager manager;
197
- }
198
-
199
- uint256[] marketIds;
200
- mapping(uint256 marketId => Market market) markets;
201
- uint256 public marketIndex;
202
- mapping(address manager => bool allowed) allowedManagers;
203
-
204
- // weth configs
205
- IWETH public WETH;
206
-
207
- bool public paused;
208
-
209
- uint256 public testVarInTheBeginning1;
210
- uint256 public testVarInTheBeginning2;
211
- uint256 public testVarInTheBeginning3;
212
- uint256 public testVarInTheBeginning4;
213
- uint256 public testVarInTheBeginning5;
214
- uint256 public testVarInTheBeginning6;
215
- uint256 public testVarInTheBeginning;
216
- uint256 public testVarInTheBeginning8;
217
- uint256 public testVarInTheBeginning9;
218
- uint256 public testVarInTheBeginning10;
219
- uint256 public testVarInTheBeginning11;
220
- uint256 public testVarInTheBeginning12;
221
- uint256 public testVarInTheBeginning13;
222
- uint256 public testVarInTheBeginning14;
223
- uint256[] public testVarInTheBeginningArray1;
224
- uint256[] public testVarInTheBeginningArray2;
225
- uint256[] public testVarInTheBeginningArray3;
226
- uint256[] public testVarInTheBeginningArray;
227
- uint256[] public testVarInTheBeginningArray5;
228
- uint256[] public testVarInTheBeginningArray6;
229
- uint256[] public testVarInTheBeginningArray7;
230
- uint256[] public testVarInTheBeginningArray8;
231
- uint256[] public testVarInTheBeginningArray9;
232
-
233
- // ------ Modifiers ------
234
-
235
- modifier isMarket(uint256 marketId) {
236
- require(marketId < marketIndex, "!m");
237
- _;
238
- }
239
-
240
- modifier timeTransitions(uint256 marketId) {
241
- if (block.timestamp > markets[marketId].closesAtTimestamp && markets[marketId].state == MarketState.open) {
242
- _nextState(marketId);
243
- }
244
- _;
245
- }
246
-
247
- modifier atState(uint256 marketId, MarketState state) {
248
- require(markets[marketId].state == state, "!ms");
249
- _;
250
- }
251
-
252
- modifier notAtState(uint256 marketId, MarketState state) {
253
- require(markets[marketId].state != state, "!ms");
254
- _;
255
- }
256
-
257
- modifier whenNotPaused() {
258
- require(!paused, "!p");
259
- _;
260
- }
261
-
262
- modifier whenPaused() {
263
- require(paused, "!p");
264
- _;
265
- }
266
-
267
- modifier marketNotPaused(uint256 marketId) {
268
- require(!paused, "p");
269
- require(!markets[marketId].paused, "mp");
270
- _;
271
- }
272
-
273
- modifier marketPaused(uint256 marketId) {
274
- require(markets[marketId].paused, "!mp");
275
- _;
276
- }
277
-
278
- modifier transitionNext(uint256 marketId) {
279
- _;
280
- _nextState(marketId);
281
- }
282
-
283
- modifier transitionLast(uint256 marketId) {
284
- _;
285
- _lastState(marketId);
286
- }
287
-
288
- modifier isWETHMarket(uint256 marketId) {
289
- require(address(WETH) != address(0), "w0");
290
- require(address(markets[marketId].token) == address(WETH), "!w");
291
- _;
292
- }
293
-
294
- // ------ Modifiers End ------
295
-
296
- /// @custom:oz-upgrades-unsafe-allow constructor
297
- constructor() {
298
- _disableInitializers();
299
- }
300
-
301
- /// @dev Initialize the contract - replaces constructor for upgradeable contracts
302
- function initialize(IWETH _WETH, address initialOwner) public initializer {
303
- __ReentrancyGuard_init();
304
- __Ownable_init(initialOwner);
305
- __UUPSUpgradeable_init();
306
-
307
- WETH = _WETH;
308
- }
309
-
310
- receive() external payable {
311
- assert(msg.sender == address(WETH)); // only accept ETH via fallback from the WETH contract
312
- }
313
-
314
- // ------ Core Functions ------
315
-
316
- /// @dev for internal use only, validates the market fees and throws if they are not valid
317
- function _validateFees(Fees memory fees) private pure {
318
- require(fees.fee <= MAX_FEE, "f>5");
319
- require(fees.treasuryFee <= MAX_FEE, "tf>5");
320
- require(fees.distributorFee <= MAX_FEE, "df>5");
321
- }
322
-
323
- /// @dev Creates a market, initializes the outcome shares pool and submits a question in Realitio
324
- function _createMarket(CreateMarketDescription memory desc) private returns (uint256 marketId) {
325
- marketId = marketIndex;
326
- marketIds.push(marketId);
327
-
328
- Market storage market = markets[marketId];
329
-
330
- IRealityETH_ERC20 realitio = IRealityETH_ERC20(desc.manager.getERC20RealitioAddress(desc.token));
331
-
332
- require(desc.value > 0, "v0");
333
- require(desc.closesAt > block.timestamp, "c<n");
334
- require(desc.arbitrator != address(0), "a0");
335
- require(desc.outcomes > 0 && desc.outcomes <= MAX_OUTCOMES, "!oc");
336
- require(address(realitio) != address(0), "r0");
337
- require(desc.realitioTimeout >= MINIMUM_REALITIO_TIMEOUT, "rt<1h");
338
- require(allowedManagers[address(desc.manager)], "!am");
339
- require(desc.manager.isAllowedToCreateMarket(desc.token, msg.sender), "m!=a");
340
-
341
- market.token = desc.token;
342
- market.closesAtTimestamp = desc.closesAt;
343
- market.state = MarketState.open;
344
-
345
- // setting up fees
346
- _validateFees(desc.buyFees);
347
- market.fees.buyFees = desc.buyFees;
348
- _validateFees(desc.sellFees);
349
- market.fees.sellFees = desc.sellFees;
350
-
351
- market.fees.treasury = desc.treasury;
352
- market.fees.distributor = desc.distributor;
353
- // setting intial value to an integer that does not map to any outcomeId
354
- market.resolution.outcomeId = MAX_UINT_256;
355
- market.outcomeCount = desc.outcomes;
356
-
357
- // creating question in realitio
358
- market.resolution.questionId = realitio.askQuestionERC20(
359
- 2,
360
- desc.question,
361
- desc.arbitrator,
362
- desc.realitioTimeout,
363
- desc.closesAt,
364
- 0,
365
- 0
366
- );
367
- market.resolution.realitio = realitio;
368
- market.resolution.realitioTimeout = desc.realitioTimeout;
369
- market.manager = desc.manager;
370
- market.creator = msg.sender;
371
-
372
- _addLiquidity(marketId, desc.value, desc.distribution);
373
-
374
- // emiting initial price events
375
- _emitMarketActionEvents(marketId);
376
- emit MarketCreated(msg.sender, marketId, desc.outcomes, desc.question, desc.image, desc.token);
377
-
378
- // incrementing market array index
379
- marketIndex += 1;
380
- }
381
-
382
- function createMarket(CreateMarketDescription calldata desc) external nonReentrant returns (uint256 marketId) {
383
- marketId = _createMarket(
384
- CreateMarketDescription({
385
- value: desc.value,
386
- closesAt: desc.closesAt,
387
- outcomes: desc.outcomes,
388
- token: desc.token,
389
- distribution: desc.distribution,
390
- question: desc.question,
391
- image: desc.image,
392
- arbitrator: desc.arbitrator,
393
- buyFees: desc.buyFees,
394
- sellFees: desc.sellFees,
395
- treasury: desc.treasury,
396
- distributor: desc.distributor,
397
- realitioTimeout: desc.realitioTimeout,
398
- manager: desc.manager
399
- })
400
- );
401
- // transferring funds
402
- desc.token.safeTransferFrom(msg.sender, address(this), desc.value);
403
- }
404
-
405
- function mintAndCreateMarket(CreateMarketDescription calldata desc) external nonReentrant returns (uint256 marketId) {
406
- // mint the amount of tokens to the user
407
- IFantasyERC20(address(desc.token)).mint(msg.sender, desc.value);
408
-
409
- marketId = _createMarket(desc);
410
- // transferring funds
411
- desc.token.safeTransferFrom(msg.sender, address(this), desc.value);
412
-
413
- return marketId;
414
- }
415
-
416
- /// @dev Calculates the number of shares bought with "amount" balance
417
- function calcBuyAmount(
418
- uint256 amount,
419
- uint256 marketId,
420
- uint256 outcomeId
421
- ) public view returns (uint256) {
422
- Market storage market = markets[marketId];
423
- require(outcomeId < market.outcomeCount, "!o");
424
-
425
- uint256[] memory outcomesShares = getMarketOutcomesShares(marketId);
426
- uint256 fee = getMarketFee(marketId);
427
- uint256 amountMinusFees = amount - ((amount * fee) / ONE);
428
- uint256 buyTokenPoolBalance = outcomesShares[outcomeId];
429
- uint256 endingOutcomeBalance = buyTokenPoolBalance * ONE;
430
- for (uint256 i; i < market.outcomeCount; ++i) {
431
- if (i != outcomeId) {
432
- uint256 outcomeShares = outcomesShares[i];
433
- endingOutcomeBalance = (endingOutcomeBalance * outcomeShares).ceildiv(outcomeShares + amountMinusFees);
434
- }
435
- }
436
- require(endingOutcomeBalance > 0, "b0");
437
-
438
- return buyTokenPoolBalance + amountMinusFees - (endingOutcomeBalance.ceildiv(ONE));
439
- }
440
-
441
- /// @dev Calculates the number of shares needed to be sold in order to receive "amount" in balance
442
- function calcSellAmount(
443
- uint256 amount,
444
- uint256 marketId,
445
- uint256 outcomeId
446
- ) public view returns (uint256) {
447
- Market storage market = markets[marketId];
448
- require(outcomeId < market.outcomeCount, "!o");
449
-
450
- uint256[] memory outcomesShares = getMarketOutcomesShares(marketId);
451
- uint256 fee = getMarketSellFee(marketId);
452
- uint256 amountPlusFees = (amount * ONE) / (ONE - fee);
453
- uint256 sellTokenPoolBalance = outcomesShares[outcomeId];
454
- uint256 endingOutcomeBalance = sellTokenPoolBalance * ONE;
455
- for (uint256 i; i < market.outcomeCount; ++i) {
456
- if (i != outcomeId) {
457
- uint256 outcomeShares = outcomesShares[i];
458
- endingOutcomeBalance = (endingOutcomeBalance * outcomeShares).ceildiv(outcomeShares - amountPlusFees);
459
- }
460
- }
461
- require(endingOutcomeBalance > 0, "b0");
462
-
463
- return amountPlusFees + endingOutcomeBalance.ceildiv(ONE) - sellTokenPoolBalance;
464
- }
465
-
466
- /// @dev Buy shares of a market outcome - returns gross amount of transaction (amount + fee)
467
- function _buy(
468
- uint256 marketId,
469
- uint256 outcomeId,
470
- uint256 minOutcomeSharesToBuy,
471
- uint256 value
472
- ) private timeTransitions(marketId) atState(marketId, MarketState.open) marketNotPaused(marketId) returns (uint256) {
473
- Market storage market = markets[marketId];
474
-
475
- uint256 shares = calcBuyAmount(value, marketId, outcomeId);
476
- require(shares >= minOutcomeSharesToBuy, "s<m");
477
- require(shares > 0, "s0");
478
-
479
- // subtracting fee from transaction value
480
- uint256 feeAmount = (value * market.fees.buyFees.fee) / ONE;
481
- market.fees.poolWeight += feeAmount;
482
- uint256 valueMinusFees = value - feeAmount;
483
-
484
- uint256 treasuryFeeAmount = (value * market.fees.buyFees.treasuryFee) / ONE;
485
- uint256 distributorFeeAmount = (value * market.fees.buyFees.distributorFee) / ONE;
486
- valueMinusFees -= treasuryFeeAmount + distributorFeeAmount;
487
-
488
- MarketOutcome storage outcome = market.outcomes[outcomeId];
489
-
490
- // Funding market shares with received funds
491
- _addSharesToMarket(marketId, valueMinusFees);
492
-
493
- require(outcome.shares.available >= shares, "s<sp");
494
-
495
- _transferOutcomeSharesfromPool(msg.sender, marketId, outcomeId, shares);
496
-
497
- // value emmited in event includes fee (gross amount)
498
- emit MarketActionTx(msg.sender, MarketAction.buy, marketId, outcomeId, shares, value, block.timestamp);
499
- _emitMarketActionEvents(marketId);
500
-
501
- // transfering treasury/distributor fees
502
- if (treasuryFeeAmount > 0) {
503
- market.token.safeTransfer(market.fees.treasury, treasuryFeeAmount);
504
- }
505
- if (distributorFeeAmount > 0) {
506
- market.token.safeTransfer(market.fees.distributor, distributorFeeAmount);
507
- }
508
-
509
- return value;
510
- }
511
-
512
- /// @dev Buy shares of a market outcome
513
- function buy(
514
- uint256 marketId,
515
- uint256 outcomeId,
516
- uint256 minOutcomeSharesToBuy,
517
- uint256 value
518
- ) external nonReentrant {
519
- Market storage market = markets[marketId];
520
- market.token.safeTransferFrom(msg.sender, address(this), value);
521
- _buy(marketId, outcomeId, minOutcomeSharesToBuy, value);
522
- }
523
-
524
- function buyWithETH(
525
- uint256 marketId,
526
- uint256 outcomeId,
527
- uint256 minOutcomeSharesToBuy
528
- ) external payable isWETHMarket(marketId) nonReentrant {
529
- uint256 value = msg.value;
530
- // wrapping and depositing funds
531
- IWETH(WETH).deposit{value: value}();
532
- _buy(marketId, outcomeId, minOutcomeSharesToBuy, value);
533
- }
534
-
535
- function referralBuy(
536
- uint256 marketId,
537
- uint256 outcomeId,
538
- uint256 minOutcomeSharesToBuy,
539
- uint256 value,
540
- string memory code
541
- ) public nonReentrant {
542
- Market storage market = markets[marketId];
543
- market.token.safeTransferFrom(msg.sender, address(this), value);
544
- _buy(marketId, outcomeId, minOutcomeSharesToBuy, value);
545
-
546
- emit Referral(msg.sender, marketId, code, MarketAction.buy, outcomeId, value, block.timestamp);
547
- }
548
-
549
- /// @dev Sell shares of a market outcome - returns gross amount of transaction (amount + fee)
550
- function _sell(
551
- uint256 marketId,
552
- uint256 outcomeId,
553
- uint256 value,
554
- uint256 maxOutcomeSharesToSell
555
- ) private timeTransitions(marketId) atState(marketId, MarketState.open) marketNotPaused(marketId) returns (uint256) {
556
- Market storage market = markets[marketId];
557
- MarketOutcome storage outcome = market.outcomes[outcomeId];
558
-
559
- uint256 shares = calcSellAmount(value, marketId, outcomeId);
560
-
561
- require(shares <= maxOutcomeSharesToSell, "s>m");
562
- require(shares > 0, "s0");
563
- require(outcome.shares.holders[msg.sender] >= shares, "s>h");
564
-
565
- _transferOutcomeSharesToPool(msg.sender, marketId, outcomeId, shares);
566
-
567
- // adding fees to transaction value
568
- uint256 fee = getMarketSellFee(marketId);
569
- uint256 oneMinusFee = ONE - fee;
570
- {
571
- uint256 feeAmount = (value * market.fees.sellFees.fee) / oneMinusFee;
572
- market.fees.poolWeight += feeAmount;
573
- }
574
- uint256 valuePlusFees = value + (value * fee) / oneMinusFee;
575
-
576
- require(market.balance >= valuePlusFees, "b<v");
577
-
578
- // Rebalancing market shares
579
- _removeSharesFromMarket(marketId, valuePlusFees);
580
-
581
- // value emmited in event includes fee (gross amount)
582
- emit MarketActionTx(msg.sender, MarketAction.sell, marketId, outcomeId, shares, valuePlusFees, block.timestamp);
583
- _emitMarketActionEvents(marketId);
584
-
585
- {
586
- uint256 treasuryFeeAmount = (value * market.fees.sellFees.treasuryFee) / oneMinusFee;
587
- uint256 distributorFeeAmount = (value * market.fees.sellFees.distributorFee) / oneMinusFee;
588
- // transfering treasury/distributor fees
589
- if (treasuryFeeAmount > 0) {
590
- market.token.safeTransfer(market.fees.treasury, treasuryFeeAmount);
591
- }
592
- if (distributorFeeAmount > 0) {
593
- market.token.safeTransfer(market.fees.distributor, distributorFeeAmount);
594
- }
595
- }
596
-
597
- return valuePlusFees;
598
- }
599
-
600
- function sell(
601
- uint256 marketId,
602
- uint256 outcomeId,
603
- uint256 value,
604
- uint256 maxOutcomeSharesToSell
605
- ) external nonReentrant {
606
- _sell(marketId, outcomeId, value, maxOutcomeSharesToSell);
607
- // Transferring funds to user
608
- Market storage market = markets[marketId];
609
- market.token.safeTransfer(msg.sender, value);
610
- }
611
-
612
- function sellToETH(
613
- uint256 marketId,
614
- uint256 outcomeId,
615
- uint256 value,
616
- uint256 maxOutcomeSharesToSell
617
- ) external isWETHMarket(marketId) nonReentrant {
618
- _sell(marketId, outcomeId, value, maxOutcomeSharesToSell);
619
-
620
- IWETH(WETH).withdraw(value);
621
- (bool sent, ) = payable(msg.sender).call{value: value}("");
622
- require(sent, "!s");
623
- }
624
-
625
- function referralSell(
626
- uint256 marketId,
627
- uint256 outcomeId,
628
- uint256 value,
629
- uint256 maxOutcomeSharesToSell,
630
- string memory code
631
- ) external nonReentrant {
632
- uint256 valuePlusFees = _sell(marketId, outcomeId, value, maxOutcomeSharesToSell);
633
- // Transferring funds to user
634
- Market storage market = markets[marketId];
635
- market.token.safeTransfer(msg.sender, value);
636
-
637
- emit Referral(msg.sender, marketId, code, MarketAction.sell, outcomeId, valuePlusFees, block.timestamp);
638
- }
639
-
640
- /// @dev Adds liquidity to a market - external
641
- function _addLiquidity(
642
- uint256 marketId,
643
- uint256 value,
644
- uint256[] memory distribution
645
- ) private timeTransitions(marketId) atState(marketId, MarketState.open) marketNotPaused(marketId) {
646
- Market storage market = markets[marketId];
647
-
648
- require(value > 0, "v0");
649
-
650
- uint256 liquidityAmount;
651
-
652
- uint256[] memory outcomesShares = getMarketOutcomesShares(marketId);
653
- uint256[] memory sendBackAmounts = new uint256[](market.outcomeCount);
654
- uint256 poolWeight = 0;
655
-
656
- if (market.liquidity > 0) {
657
- require(distribution.length == 0, "!d");
658
-
659
- // part of the liquidity is exchanged for outcome shares if market is not balanced
660
- for (uint256 i; i < market.outcomeCount; ++i) {
661
- uint256 outcomeShares = outcomesShares[i];
662
- if (poolWeight < outcomeShares) poolWeight = outcomeShares;
663
- }
664
-
665
- for (uint256 i; i < market.outcomeCount; ++i) {
666
- uint256 remaining = (value * outcomesShares[i]) / poolWeight;
667
- sendBackAmounts[i] = value - remaining;
668
- }
669
-
670
- liquidityAmount = (value * market.liquidity) / poolWeight;
671
-
672
- // re-balancing fees pool
673
- _rebalanceFeesPool(marketId, liquidityAmount, MarketAction.addLiquidity);
674
- } else {
675
- uint256 distributionLength = distribution.length;
676
- // funding market with no liquidity
677
- if (distributionLength > 0) {
678
- require(distributionLength == market.outcomeCount, "d!=oc");
679
-
680
- uint256 maxHint = 0;
681
- for (uint256 i; i < distributionLength; ++i) {
682
- uint256 hint = distribution[i];
683
- if (maxHint < hint) maxHint = hint;
684
- }
685
-
686
- for (uint256 i; i < distributionLength; ++i) {
687
- uint256 remaining = (value * distribution[i]) / maxHint;
688
- require(remaining > 0, "!d");
689
- sendBackAmounts[i] = value - remaining;
690
- }
691
- }
692
-
693
- // funding market with total liquidity amount
694
- liquidityAmount = value;
695
- }
696
-
697
- // funding market
698
- market.liquidity = market.liquidity + liquidityAmount;
699
- market.liquidityShares[msg.sender] = market.liquidityShares[msg.sender] + liquidityAmount;
700
-
701
- _addSharesToMarket(marketId, value);
702
-
703
- {
704
- // transform sendBackAmounts to array of amounts added
705
- for (uint256 i; i < market.outcomeCount; ++i) {
706
- if (sendBackAmounts[i] > 0) {
707
- _transferOutcomeSharesfromPool(msg.sender, marketId, i, sendBackAmounts[i]);
708
- }
709
- }
710
-
711
- // emitting events, using outcome 0 for price reference
712
- uint256 referencePrice = getMarketOutcomePrice(marketId, 0);
713
-
714
- for (uint256 i; i < market.outcomeCount; ++i) {
715
- if (sendBackAmounts[i] > 0) {
716
- // outcome price = outcome shares / reference outcome shares * reference outcome price
717
- uint256 outcomePrice = (referencePrice * market.outcomes[0].shares.available) /
718
- market.outcomes[i].shares.available;
719
-
720
- emit MarketActionTx(
721
- msg.sender,
722
- MarketAction.buy,
723
- marketId,
724
- i,
725
- sendBackAmounts[i],
726
- (sendBackAmounts[i] * outcomePrice) / ONE, // price * shares
727
- block.timestamp
728
- );
729
- }
730
- }
731
- }
732
-
733
- uint256 liquidityPrice = getMarketLiquidityPrice(marketId);
734
- uint256 liquidityValue = (liquidityPrice * liquidityAmount) / ONE;
735
-
736
- emit MarketActionTx(
737
- msg.sender,
738
- MarketAction.addLiquidity,
739
- marketId,
740
- 0,
741
- liquidityAmount,
742
- liquidityValue,
743
- block.timestamp
744
- );
745
- emit MarketLiquidity(marketId, market.liquidity, liquidityPrice, block.timestamp);
746
- }
747
-
748
- function addLiquidity(uint256 marketId, uint256 value) external nonReentrant {
749
- uint256[] memory distribution = new uint256[](0);
750
- _addLiquidity(marketId, value, distribution);
751
-
752
- Market storage market = markets[marketId];
753
- market.token.safeTransferFrom(msg.sender, address(this), value);
754
- }
755
-
756
- /// @dev Removes liquidity to a market - external
757
- function _removeLiquidity(uint256 marketId, uint256 shares)
758
- private
759
- timeTransitions(marketId)
760
- atState(marketId, MarketState.open)
761
- marketNotPaused(marketId)
762
- returns (uint256)
763
- {
764
- Market storage market = markets[marketId];
765
-
766
- // removing 100% of the liquidity is not allowed
767
- require(shares < market.liquidity, "s>l");
768
- require(market.liquidityShares[msg.sender] >= shares, "s>h");
769
-
770
- // re-balancing fees pool
771
- _rebalanceFeesPool(marketId, shares, MarketAction.removeLiquidity);
772
-
773
- uint256[] memory outcomesShares = getMarketOutcomesShares(marketId);
774
- uint256[] memory sendAmounts = new uint256[](market.outcomeCount);
775
- uint256 poolWeight = MAX_UINT_256;
776
-
777
- // part of the liquidity is exchanged for outcome shares if market is not balanced
778
- for (uint256 i; i < market.outcomeCount; ++i) {
779
- uint256 outcomeShares = outcomesShares[i];
780
- if (poolWeight > outcomeShares) poolWeight = outcomeShares;
781
- }
782
-
783
- uint256 liquidityAmount = (shares * poolWeight) / market.liquidity;
784
-
785
- for (uint256 i; i < market.outcomeCount; ++i) {
786
- sendAmounts[i] = (outcomesShares[i] * shares) / market.liquidity;
787
- sendAmounts[i] = sendAmounts[i] - liquidityAmount;
788
- }
789
-
790
- // removing liquidity from market
791
- _removeSharesFromMarket(marketId, liquidityAmount);
792
- market.liquidity = market.liquidity - shares;
793
- // removing liquidity tokens from market creator
794
- market.liquidityShares[msg.sender] = market.liquidityShares[msg.sender] - shares;
795
-
796
- for (uint256 i; i < market.outcomeCount; ++i) {
797
- if (sendAmounts[i] > 0) {
798
- _transferOutcomeSharesfromPool(msg.sender, marketId, i, sendAmounts[i]);
799
- }
800
- }
801
-
802
- // emitting events, using outcome 0 for price reference
803
- uint256 referencePrice = getMarketOutcomePrice(marketId, 0);
804
-
805
- for (uint256 i; i < market.outcomeCount; ++i) {
806
- if (sendAmounts[i] > 0) {
807
- // outcome price = outcome shares / reference outcome shares * reference outcome price
808
- uint256 outcomePrice = (referencePrice * market.outcomes[0].shares.available) /
809
- market.outcomes[i].shares.available;
810
-
811
- emit MarketActionTx(
812
- msg.sender,
813
- MarketAction.buy,
814
- marketId,
815
- i,
816
- sendAmounts[i],
817
- (sendAmounts[i] * outcomePrice) / ONE, // price * shares
818
- block.timestamp
819
- );
820
- }
821
- }
822
-
823
- emit MarketActionTx(
824
- msg.sender,
825
- MarketAction.removeLiquidity,
826
- marketId,
827
- 0,
828
- shares,
829
- liquidityAmount,
830
- block.timestamp
831
- );
832
- emit MarketLiquidity(marketId, market.liquidity, getMarketLiquidityPrice(marketId), block.timestamp);
833
-
834
- return liquidityAmount;
835
- }
836
-
837
- function removeLiquidity(uint256 marketId, uint256 shares) external nonReentrant {
838
- uint256 value = _removeLiquidity(marketId, shares);
839
- // transferring user funds from liquidity removed
840
- Market storage market = markets[marketId];
841
- market.token.safeTransfer(msg.sender, value);
842
- }
843
-
844
- /// @dev Fetches winning outcome from Realitio and resolves the market
845
- function resolveMarketOutcome(uint256 marketId)
846
- external
847
- timeTransitions(marketId)
848
- atState(marketId, MarketState.closed)
849
- transitionNext(marketId)
850
- returns (uint256 outcomeId)
851
- {
852
- Market storage market = markets[marketId];
853
-
854
- // will fail if question is not finalized
855
- outcomeId = uint256(market.resolution.realitio.resultFor(market.resolution.questionId));
856
-
857
- market.resolution.outcomeId = outcomeId;
858
-
859
- emit MarketResolved(msg.sender, marketId, outcomeId, block.timestamp, false);
860
- _emitMarketActionEvents(marketId);
861
- }
862
-
863
- /// @dev overrides market resolution, instead of using realitio
864
- function adminResolveMarketOutcome(uint256 marketId, uint256 outcomeId)
865
- external
866
- notAtState(marketId, MarketState.resolved)
867
- transitionLast(marketId)
868
- returns (uint256)
869
- {
870
- Market storage market = markets[marketId];
871
-
872
- require(market.manager.isAllowedToEditMarket(market.token, msg.sender), "not allowed to resolve market");
873
-
874
- market.resolution.outcomeId = outcomeId;
875
-
876
- emit MarketResolved(msg.sender, marketId, outcomeId, block.timestamp, true);
877
- _emitMarketActionEvents(marketId);
878
-
879
- return market.resolution.outcomeId;
880
- }
881
-
882
- /// @dev pauses a market, no trading allowed
883
- function adminPauseMarket(uint256 marketId) external isMarket(marketId) marketNotPaused(marketId) nonReentrant {
884
- Market storage market = markets[marketId];
885
- require(market.manager.isAllowedToEditMarket(market.token, msg.sender), "not allowed to pause market");
886
-
887
- market.paused = true;
888
- emit MarketPaused(msg.sender, marketId, true, block.timestamp);
889
- }
890
-
891
- /// @dev unpauses a market, trading allowed
892
- function adminUnpauseMarket(uint256 marketId) external isMarket(marketId) marketPaused(marketId) nonReentrant {
893
- Market storage market = markets[marketId];
894
- require(market.manager.isAllowedToEditMarket(market.token, msg.sender), "not allowed to unpause market");
895
-
896
- market.paused = false;
897
- emit MarketPaused(msg.sender, marketId, false, block.timestamp);
898
- }
899
-
900
- /// @dev overrides market close date
901
- function adminSetMarketCloseDate(uint256 marketId, uint256 closesAt)
902
- external
903
- isMarket(marketId)
904
- notAtState(marketId, MarketState.resolved)
905
- {
906
- Market storage market = markets[marketId];
907
- require(market.manager.isAllowedToEditMarket(market.token, msg.sender), "not allowed to set close date");
908
-
909
- require(closesAt > block.timestamp, "resolution before current date");
910
- market.closesAtTimestamp = closesAt;
911
- emit MarketCloseDateEdited(msg.sender, marketId, closesAt, block.timestamp);
912
- }
913
-
914
- /// @dev Allows holders of resolved outcome shares to claim earnings.
915
- function _claimWinnings(uint256 marketId)
916
- private
917
- atState(marketId, MarketState.resolved)
918
- marketNotPaused(marketId)
919
- returns (uint256 value)
920
- {
921
- Market storage market = markets[marketId];
922
- MarketOutcome storage resolvedOutcome = market.outcomes[market.resolution.outcomeId];
923
-
924
- require(!isMarketVoided(marketId), "mv");
925
- require(resolvedOutcome.shares.holders[msg.sender] > 0, "!h");
926
- require(!resolvedOutcome.shares.claims[msg.sender], "!c");
927
-
928
- // 1 share => price = 1
929
- value = resolvedOutcome.shares.holders[msg.sender];
930
-
931
- // assuring market has enough funds
932
- require(market.balance >= value, "b<v");
933
-
934
- market.balance = market.balance - value;
935
- resolvedOutcome.shares.claims[msg.sender] = true;
936
-
937
- emit MarketActionTx(
938
- msg.sender,
939
- MarketAction.claimWinnings,
940
- marketId,
941
- market.resolution.outcomeId,
942
- resolvedOutcome.shares.holders[msg.sender],
943
- value,
944
- block.timestamp
945
- );
946
- }
947
-
948
- function claimWinnings(uint256 marketId) external nonReentrant {
949
- uint256 value = _claimWinnings(marketId);
950
- // transferring user funds from winnings claimed
951
- Market storage market = markets[marketId];
952
- market.token.safeTransfer(msg.sender, value);
953
- }
954
-
955
- /// @dev Allows holders of voided outcome shares to claim balance back.
956
- function _claimVoidedOutcomeShares(uint256 marketId, uint256 outcomeId)
957
- private
958
- atState(marketId, MarketState.resolved)
959
- marketNotPaused(marketId)
960
- returns (uint256 value)
961
- {
962
- Market storage market = markets[marketId];
963
- MarketOutcome storage outcome = market.outcomes[outcomeId];
964
-
965
- require(isMarketVoided(marketId), "!mv");
966
- require(outcome.shares.holders[msg.sender] > 0, "!h");
967
- require(!outcome.shares.voidedClaims[msg.sender], "!c");
968
-
969
- // voided market - shares are valued at last market price
970
- uint256 price = getMarketOutcomePrice(marketId, outcomeId);
971
- value = (price * outcome.shares.holders[msg.sender]) / ONE;
972
-
973
- // assuring market has enough funds
974
- require(market.balance >= value, "b<v");
975
-
976
- market.balance = market.balance - value;
977
- outcome.shares.voidedClaims[msg.sender] = true;
978
-
979
- emit MarketActionTx(
980
- msg.sender,
981
- MarketAction.claimVoided,
982
- marketId,
983
- outcomeId,
984
- outcome.shares.holders[msg.sender],
985
- value,
986
- block.timestamp
987
- );
988
-
989
- return value;
990
- }
991
-
992
- function claimVoidedOutcomeShares(uint256 marketId, uint256 outcomeId) external nonReentrant {
993
- uint256 value = _claimVoidedOutcomeShares(marketId, outcomeId);
994
- // transferring user funds from voided outcome shares claimed
995
- Market storage market = markets[marketId];
996
- market.token.safeTransfer(msg.sender, value);
997
- }
998
-
999
- /// @dev Allows liquidity providers to claim earnings from liquidity providing.
1000
- function _claimLiquidity(uint256 marketId)
1001
- private
1002
- atState(marketId, MarketState.resolved)
1003
- marketNotPaused(marketId)
1004
- returns (uint256 value)
1005
- {
1006
- Market storage market = markets[marketId];
1007
-
1008
- require(market.liquidityShares[msg.sender] > 0, "!h");
1009
- require(!market.liquidityClaims[msg.sender], "!c");
1010
-
1011
- // value = total resolved outcome pool shares * pool share (%)
1012
- uint256 liquidityPrice = getMarketLiquidityPrice(marketId);
1013
- value = (liquidityPrice * market.liquidityShares[msg.sender]) / ONE;
1014
-
1015
- // assuring market has enough funds
1016
- require(market.balance >= value, "b<v");
1017
-
1018
- market.balance = market.balance - value;
1019
- market.liquidityClaims[msg.sender] = true;
1020
-
1021
- emit MarketActionTx(
1022
- msg.sender,
1023
- MarketAction.claimLiquidity,
1024
- marketId,
1025
- 0,
1026
- market.liquidityShares[msg.sender],
1027
- value,
1028
- block.timestamp
1029
- );
1030
- }
1031
-
1032
- function claimLiquidity(uint256 marketId) external nonReentrant {
1033
- uint256 value = _claimLiquidity(marketId);
1034
- // transferring user funds from liquidity claimed
1035
- Market storage market = markets[marketId];
1036
- market.token.safeTransfer(msg.sender, value);
1037
-
1038
- // claiming any pending fees
1039
- uint256 feesValue = _claimFees(marketId);
1040
- if (feesValue > 0) {
1041
- market.token.safeTransfer(msg.sender, feesValue);
1042
- }
1043
- }
1044
-
1045
- /// @dev Allows liquidity providers to claim their fees share from fees pool
1046
- function _claimFees(uint256 marketId) private marketNotPaused(marketId) returns (uint256 value) {
1047
- Market storage market = markets[marketId];
1048
-
1049
- value = getUserClaimableFees(marketId, msg.sender);
1050
-
1051
- if (value > 0) {
1052
- market.fees.claimed[msg.sender] = market.fees.claimed[msg.sender] + value;
1053
- }
1054
-
1055
- emit MarketActionTx(
1056
- msg.sender,
1057
- MarketAction.claimFees,
1058
- marketId,
1059
- 0,
1060
- market.liquidityShares[msg.sender],
1061
- value,
1062
- block.timestamp
1063
- );
1064
- }
1065
-
1066
- function claimFees(uint256 marketId) public nonReentrant {
1067
- uint256 value = _claimFees(marketId);
1068
- // transferring user funds from fees claimed
1069
- Market storage market = markets[marketId];
1070
- market.token.safeTransfer(msg.sender, value);
1071
- }
1072
-
1073
- /// @dev Rebalances the fees pool. Needed in every AddLiquidity / RemoveLiquidity call
1074
- function _rebalanceFeesPool(
1075
- uint256 marketId,
1076
- uint256 liquidityShares,
1077
- MarketAction action
1078
- ) private {
1079
- Market storage market = markets[marketId];
1080
-
1081
- uint256 poolWeight = (liquidityShares * market.fees.poolWeight) / market.liquidity;
1082
-
1083
- if (action == MarketAction.addLiquidity) {
1084
- market.fees.poolWeight += poolWeight;
1085
- market.fees.claimed[msg.sender] += poolWeight;
1086
- } else {
1087
- market.fees.poolWeight -= poolWeight;
1088
- market.fees.claimed[msg.sender] = market.fees.claimed[msg.sender] - poolWeight;
1089
- }
1090
- }
1091
-
1092
- /// @dev Transitions market to next state
1093
- function _nextState(uint256 marketId) private {
1094
- Market storage market = markets[marketId];
1095
- market.state = MarketState(uint256(market.state) + 1);
1096
- }
1097
-
1098
- /// @dev Transitions market to last state
1099
- function _lastState(uint256 marketId) private {
1100
- Market storage market = markets[marketId];
1101
- market.state = MarketState.resolved;
1102
- }
1103
-
1104
- /// @dev Emits a outcome price event for every outcome
1105
- function _emitMarketActionEvents(uint256 marketId) private {
1106
- Market storage market = markets[marketId];
1107
- uint256[] memory outcomeShares = new uint256[](market.outcomeCount);
1108
-
1109
- for (uint256 i; i < market.outcomeCount; ++i) {
1110
- outcomeShares[i] = market.outcomes[i].shares.available;
1111
- }
1112
-
1113
- emit MarketOutcomeShares(marketId, block.timestamp, outcomeShares, market.liquidity);
1114
- }
1115
-
1116
- /// @dev Adds outcome shares to shares pool
1117
- function _addSharesToMarket(uint256 marketId, uint256 shares) private {
1118
- Market storage market = markets[marketId];
1119
-
1120
- for (uint256 i; i < market.outcomeCount; ++i) {
1121
- MarketOutcome storage outcome = market.outcomes[i];
1122
-
1123
- outcome.shares.available = outcome.shares.available + shares;
1124
- outcome.shares.total = outcome.shares.total + shares;
1125
-
1126
- // only adding to market total shares, the available remains
1127
- market.sharesAvailable = market.sharesAvailable + shares;
1128
- }
1129
-
1130
- market.balance = market.balance + shares;
1131
- }
1132
-
1133
- /// @dev Removes outcome shares from shares pool
1134
- function _removeSharesFromMarket(uint256 marketId, uint256 shares) private {
1135
- Market storage market = markets[marketId];
1136
-
1137
- for (uint256 i; i < market.outcomeCount; ++i) {
1138
- MarketOutcome storage outcome = market.outcomes[i];
1139
-
1140
- outcome.shares.available = outcome.shares.available - shares;
1141
- outcome.shares.total = outcome.shares.total - shares;
1142
-
1143
- // only subtracting from market total shares, the available remains
1144
- market.sharesAvailable = market.sharesAvailable - shares;
1145
- }
1146
-
1147
- market.balance = market.balance - shares;
1148
- }
1149
-
1150
- /// @dev Transfer outcome shares from pool to user balance
1151
- function _transferOutcomeSharesfromPool(
1152
- address user,
1153
- uint256 marketId,
1154
- uint256 outcomeId,
1155
- uint256 shares
1156
- ) private {
1157
- Market storage market = markets[marketId];
1158
- MarketOutcome storage outcome = market.outcomes[outcomeId];
1159
-
1160
- // transfering shares from shares pool to user
1161
- outcome.shares.holders[user] = outcome.shares.holders[user] + shares;
1162
- outcome.shares.available = outcome.shares.available - shares;
1163
- market.sharesAvailable = market.sharesAvailable - shares;
1164
- }
1165
-
1166
- /// @dev Transfer outcome shares from user balance back to pool
1167
- function _transferOutcomeSharesToPool(
1168
- address user,
1169
- uint256 marketId,
1170
- uint256 outcomeId,
1171
- uint256 shares
1172
- ) private {
1173
- Market storage market = markets[marketId];
1174
- MarketOutcome storage outcome = market.outcomes[outcomeId];
1175
-
1176
- // adding shares back to pool
1177
- outcome.shares.holders[user] = outcome.shares.holders[user] - shares;
1178
- outcome.shares.available = outcome.shares.available + shares;
1179
- market.sharesAvailable = market.sharesAvailable + shares;
1180
- }
1181
-
1182
- // ------ Core Functions End ------
1183
-
1184
- // ------ Getters ------
1185
-
1186
- function getUserMarketShares(uint256 marketId, address user)
1187
- external
1188
- view
1189
- returns (uint256 liquidity, uint256[] memory outcomes)
1190
- {
1191
- Market storage market = markets[marketId];
1192
- uint256[] memory outcomeShares = new uint256[](market.outcomeCount);
1193
-
1194
- for (uint256 i; i < market.outcomeCount; ++i) {
1195
- outcomeShares[i] = market.outcomes[i].shares.holders[user];
1196
- }
1197
-
1198
- return (market.liquidityShares[user], outcomeShares);
1199
- }
1200
-
1201
- function getUserClaimStatus(uint256 marketId, address user)
1202
- external
1203
- view
1204
- returns (
1205
- bool winningsToClaim,
1206
- bool winningsClaimed,
1207
- bool liquidityToClaim,
1208
- bool liquidityClaimed,
1209
- uint256 claimableFees
1210
- )
1211
- {
1212
- Market storage market = markets[marketId];
1213
-
1214
- // market still not resolved
1215
- if (market.state != MarketState.resolved) {
1216
- return (false, false, false, false, getUserClaimableFees(marketId, user));
1217
- }
1218
-
1219
- MarketOutcome storage outcome = market.outcomes[market.resolution.outcomeId];
1220
-
1221
- return (
1222
- outcome.shares.holders[user] > 0,
1223
- outcome.shares.claims[user],
1224
- market.liquidityShares[user] > 0,
1225
- market.liquidityClaims[user],
1226
- getUserClaimableFees(marketId, user)
1227
- );
1228
- }
1229
-
1230
- function getUserLiquidityPoolShare(uint256 marketId, address user) external view returns (uint256) {
1231
- Market storage market = markets[marketId];
1232
-
1233
- return (market.liquidityShares[user] * ONE) / market.liquidity;
1234
- }
1235
-
1236
- function getUserClaimableFees(uint256 marketId, address user) public view returns (uint256) {
1237
- Market storage market = markets[marketId];
1238
-
1239
- uint256 rawAmount = (market.fees.poolWeight * market.liquidityShares[user]) / market.liquidity;
1240
-
1241
- // No fees left to claim
1242
- if (market.fees.claimed[user] > rawAmount) return 0;
1243
-
1244
- return rawAmount - market.fees.claimed[user];
1245
- }
1246
-
1247
- function getMarkets() external view returns (uint256[] memory) {
1248
- return marketIds;
1249
- }
1250
-
1251
- function getMarketData(uint256 marketId)
1252
- external
1253
- view
1254
- returns (
1255
- MarketState state,
1256
- uint256 closesAt,
1257
- uint256 liquidity,
1258
- uint256 balance,
1259
- uint256 sharesAvailable,
1260
- int256 resolvedOutcomeId
1261
- )
1262
- {
1263
- Market storage market = markets[marketId];
1264
-
1265
- return (
1266
- market.state,
1267
- market.closesAtTimestamp,
1268
- market.liquidity,
1269
- market.balance,
1270
- market.sharesAvailable,
1271
- getMarketResolvedOutcome(marketId)
1272
- );
1273
- }
1274
-
1275
- function getMarketAltData(uint256 marketId)
1276
- external
1277
- view
1278
- returns (
1279
- uint256 buyFee,
1280
- bytes32 questionId,
1281
- uint256 questionIdUint,
1282
- IERC20 token,
1283
- uint256 buyTreasuryFee,
1284
- address treasury,
1285
- IRealityETH_ERC20 realitio,
1286
- uint256 realitioTimeout,
1287
- IPredictionMarketV3Manager manager
1288
- )
1289
- {
1290
- Market storage market = markets[marketId];
1291
-
1292
- return (
1293
- market.fees.buyFees.fee,
1294
- market.resolution.questionId,
1295
- uint256(market.resolution.questionId),
1296
- market.token,
1297
- market.fees.buyFees.treasuryFee,
1298
- market.fees.treasury,
1299
- market.resolution.realitio,
1300
- market.resolution.realitioTimeout,
1301
- market.manager
1302
- );
1303
- }
1304
-
1305
- function getMarketCreator(uint256 marketId) external view returns (address) {
1306
- Market storage market = markets[marketId];
1307
-
1308
- return market.creator;
1309
- }
1310
-
1311
- function getMarketQuestion(uint256 marketId) external view returns (bytes32) {
1312
- Market storage market = markets[marketId];
1313
-
1314
- return (market.resolution.questionId);
1315
- }
1316
-
1317
- function getMarketPrices(uint256 marketId) external view returns (uint256 liquidity, uint256[] memory outcomes) {
1318
- Market storage market = markets[marketId];
1319
- uint256[] memory prices = new uint256[](market.outcomeCount);
1320
-
1321
- for (uint256 i; i < market.outcomeCount; ++i) {
1322
- prices[i] = getMarketOutcomePrice(marketId, i);
1323
- }
1324
-
1325
- return (getMarketLiquidityPrice(marketId), prices);
1326
- }
1327
-
1328
- function getMarketShares(uint256 marketId) external view returns (uint256 liquidity, uint256[] memory outcomes) {
1329
- Market storage market = markets[marketId];
1330
- uint256[] memory outcomeShares = new uint256[](market.outcomeCount);
1331
-
1332
- for (uint256 i; i < market.outcomeCount; ++i) {
1333
- outcomeShares[i] = market.outcomes[i].shares.available;
1334
- }
1335
-
1336
- return (market.liquidity, outcomeShares);
1337
- }
1338
-
1339
- function getMarketLiquidityPrice(uint256 marketId) public view returns (uint256) {
1340
- Market storage market = markets[marketId];
1341
-
1342
- if (market.state == MarketState.resolved && !isMarketVoided(marketId)) {
1343
- // resolved market, outcome prices are either 0 or 1
1344
- // final liquidity price = outcome shares / liquidity shares
1345
- return (market.outcomes[market.resolution.outcomeId].shares.available * ONE) / market.liquidity;
1346
- }
1347
-
1348
- // liquidity price = # outcomes / (liquidity * sum (1 / every outcome shares)
1349
- uint256 marketSharesSum = 0;
1350
-
1351
- for (uint256 i; i < market.outcomeCount; ++i) {
1352
- MarketOutcome storage outcome = market.outcomes[i];
1353
-
1354
- marketSharesSum = marketSharesSum + (ONE * ONE) / outcome.shares.available;
1355
- }
1356
-
1357
- return (market.outcomeCount * ONE * ONE * ONE) / market.liquidity / marketSharesSum;
1358
- }
1359
-
1360
- function getMarketResolvedOutcome(uint256 marketId) public view returns (int256) {
1361
- Market storage market = markets[marketId];
1362
-
1363
- // returning -1 if market still not resolved
1364
- if (market.state != MarketState.resolved) {
1365
- return -1;
1366
- }
1367
-
1368
- return int256(market.resolution.outcomeId);
1369
- }
1370
-
1371
- function isMarketVoided(uint256 marketId) public view returns (bool) {
1372
- Market storage market = markets[marketId];
1373
-
1374
- // market still not resolved, still in valid state
1375
- if (market.state != MarketState.resolved) {
1376
- return false;
1377
- }
1378
-
1379
- // resolved market id does not match any of the market ids
1380
- return market.resolution.outcomeId >= market.outcomeCount;
1381
- }
1382
-
1383
- function getMarketBuyFee(uint256 marketId) public view returns (uint256) {
1384
- Market storage market = markets[marketId];
1385
-
1386
- return market.fees.buyFees.fee + market.fees.buyFees.treasuryFee + market.fees.buyFees.distributorFee;
1387
- }
1388
-
1389
- function getMarketSellFee(uint256 marketId) public view returns (uint256) {
1390
- Market storage market = markets[marketId];
1391
-
1392
- return market.fees.sellFees.fee + market.fees.sellFees.treasuryFee + market.fees.sellFees.distributorFee;
1393
- }
1394
-
1395
- // alias of getMarketBuyFee, used for compatibility
1396
- function getMarketFee(uint256 marketId) public view returns (uint256) {
1397
- return getMarketBuyFee(marketId);
1398
- }
1399
-
1400
- function getMarketFees(uint256 marketId)
1401
- external
1402
- view
1403
- returns (
1404
- Fees memory buyFees,
1405
- Fees memory sellFees,
1406
- address treasury,
1407
- address distributor
1408
- )
1409
- {
1410
- Market storage market = markets[marketId];
1411
-
1412
- return (market.fees.buyFees, market.fees.sellFees, market.fees.treasury, market.fees.distributor);
1413
- }
1414
-
1415
- // ------ Outcome Getters ------
1416
-
1417
- function getMarketOutcomeIds(uint256 marketId) external view returns (uint256[] memory outcomeIds) {
1418
- Market storage market = markets[marketId];
1419
- outcomeIds = new uint256[](market.outcomeCount);
1420
-
1421
- for (uint256 i; i < market.outcomeCount; ++i) {
1422
- outcomeIds[i] = i;
1423
- }
1424
- }
1425
-
1426
- function getMarketOutcomePrice(uint256 marketId, uint256 outcomeId) public view returns (uint256) {
1427
- Market storage market = markets[marketId];
1428
-
1429
- if (market.state == MarketState.resolved && !isMarketVoided(marketId)) {
1430
- // resolved market, price is either 0 or 1
1431
- return outcomeId == market.resolution.outcomeId ? ONE : 0;
1432
- }
1433
-
1434
- // outcome price = 1 / (1 + sum(outcome shares / every outcome shares))
1435
- uint256 div = ONE;
1436
- for (uint256 i; i < market.outcomeCount; ++i) {
1437
- if (i == outcomeId) continue;
1438
-
1439
- div = div + (market.outcomes[outcomeId].shares.available * ONE) / market.outcomes[i].shares.available;
1440
- }
1441
-
1442
- return (ONE * ONE) / div;
1443
- }
1444
-
1445
- function getMarketOutcomeData(uint256 marketId, uint256 outcomeId)
1446
- external
1447
- view
1448
- returns (
1449
- uint256 price,
1450
- uint256 availableShares,
1451
- uint256 totalShares
1452
- )
1453
- {
1454
- Market storage market = markets[marketId];
1455
- MarketOutcome storage outcome = market.outcomes[outcomeId];
1456
-
1457
- return (getMarketOutcomePrice(marketId, outcomeId), outcome.shares.available, outcome.shares.total);
1458
- }
1459
-
1460
- function getMarketOutcomesShares(uint256 marketId) public view returns (uint256[] memory shares) {
1461
- Market storage market = markets[marketId];
1462
-
1463
- shares = new uint256[](market.outcomeCount);
1464
- for (uint256 i; i < market.outcomeCount; ++i) {
1465
- shares[i] = market.outcomes[i].shares.available;
1466
- }
1467
- }
1468
-
1469
- function getMarketPaused(uint256 marketId) external view returns (bool) {
1470
- Market storage market = markets[marketId];
1471
-
1472
- return market.paused;
1473
- }
1474
-
1475
- // ------ Ownable Setters ------
1476
-
1477
- function setAllowedManager(address manager, bool allowed) external onlyOwner {
1478
- allowedManagers[manager] = allowed;
1479
- emit AllowedManagerSet(manager, allowed);
1480
- }
1481
-
1482
- function withdraw(address token, uint256 amount) external onlyOwner {
1483
- IERC20(token).safeTransfer(msg.sender, amount);
1484
- }
1485
-
1486
- function pause() external onlyOwner whenNotPaused {
1487
- paused = true;
1488
- emit Paused(true, msg.sender);
1489
- }
1490
-
1491
- function unpause() external onlyOwner whenPaused {
1492
- paused = false;
1493
- emit Paused(false, msg.sender);
1494
- }
1495
-
1496
- function setTestVarInTheBeginning(uint256 _testVarInTheBeginning) external {
1497
- testVarInTheBeginning = _testVarInTheBeginning;
1498
- }
1499
-
1500
- function setTestVarInTheBeginningArray(uint256[] memory _testVarInTheBeginningArray) external {
1501
- testVarInTheBeginningArray = _testVarInTheBeginningArray;
1502
- }
1503
-
1504
- // ------ Upgrade Authorization ------
1505
-
1506
- /// @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract
1507
- function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
1508
- }