polkamarkets-js 1.0.1 → 3.1.0
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/.openzeppelin/unknown-1337.json +2056 -0
- package/CONTRIBUTING.md +36 -0
- package/README.md +24 -25
- package/_book/README.md +590 -0
- package/_book/core.md +50 -0
- package/_book/gitbook/fonts/fontawesome/FontAwesome.otf +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg +685 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 +0 -0
- package/_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js +240 -0
- package/_book/gitbook/gitbook-plugin-fontsettings/website.css +291 -0
- package/_book/gitbook/gitbook-plugin-highlight/ebook.css +135 -0
- package/_book/gitbook/gitbook-plugin-highlight/website.css +434 -0
- package/_book/gitbook/gitbook-plugin-lunr/lunr.min.js +7 -0
- package/_book/gitbook/gitbook-plugin-lunr/search-lunr.js +59 -0
- package/_book/gitbook/gitbook-plugin-search/lunr.min.js +7 -0
- package/_book/gitbook/gitbook-plugin-search/search-engine.js +50 -0
- package/_book/gitbook/gitbook-plugin-search/search.css +35 -0
- package/_book/gitbook/gitbook-plugin-search/search.js +213 -0
- package/_book/gitbook/gitbook-plugin-sharing/buttons.js +90 -0
- package/_book/gitbook/gitbook.js +4 -0
- package/_book/gitbook/images/apple-touch-icon-precomposed-152.png +0 -0
- package/_book/gitbook/images/favicon.ico +0 -0
- package/_book/gitbook/style.css +9 -0
- package/_book/gitbook/theme.js +4 -0
- package/_book/index.html +705 -0
- package/_book/intro.md +32 -0
- package/_book/search_index.json +1 -0
- package/book.json +8 -0
- package/build/contracts/AccessControl.json +1 -0
- package/build/contracts/AccessControlEnumerable.json +1 -0
- package/build/contracts/Achievements.json +1 -0
- package/build/contracts/Address.json +1 -0
- package/build/contracts/BalanceHolder.json +1 -0
- package/build/contracts/BalanceHolder_ERC20.json +1 -0
- package/build/contracts/CeilDiv.json +1 -0
- package/build/contracts/Clones.json +1 -0
- package/build/contracts/Context.json +1 -0
- package/build/contracts/Counters.json +1 -0
- package/build/contracts/ERC165.json +1 -0
- package/build/contracts/ERC20.json +1 -0
- package/build/contracts/ERC20Burnable.json +1 -0
- package/build/contracts/ERC20Pausable.json +1 -0
- package/build/contracts/ERC20PresetMinterPauser.json +1 -0
- package/build/contracts/ERC721.json +1 -0
- package/build/contracts/EnumerableMap.json +1 -0
- package/build/contracts/EnumerableSet.json +1 -0
- package/build/contracts/FantasyERC20.json +1 -0
- package/build/contracts/IAccessControl.json +1 -0
- package/build/contracts/IAccessControlEnumerable.json +1 -0
- package/build/contracts/IBalanceHolder_ERC20.json +1 -0
- package/build/contracts/IERC165.json +1 -0
- package/build/contracts/IERC20.json +1 -0
- package/build/contracts/IERC20Metadata.json +1 -0
- package/build/contracts/IERC20Permit.json +1 -0
- package/build/contracts/IERC721.json +1 -0
- package/build/contracts/IERC721Enumerable.json +1 -0
- package/build/contracts/IERC721Metadata.json +1 -0
- package/build/contracts/IERC721Receiver.json +1 -0
- package/build/contracts/IFantasyERC20.json +1 -0
- package/build/contracts/IPredictionMarketV3.json +1 -0
- package/build/contracts/IPredictionMarketV3Factory.json +1 -0
- package/build/contracts/IPredictionMarketV3Manager.json +1 -0
- package/build/contracts/IRealityETH_ERC20.json +1 -0
- package/build/contracts/IRealityETH_IERC20.json +1 -0
- package/build/contracts/IWETH.json +1 -0
- package/build/contracts/LandFactory.json +1 -0
- package/build/contracts/Math.json +1 -0
- package/build/contracts/Migrations.json +1 -0
- package/build/contracts/Ownable.json +1 -0
- package/build/contracts/Pausable.json +1 -0
- package/build/contracts/PredictionMarket.json +1 -0
- package/build/contracts/PredictionMarketV2.json +1 -0
- package/build/contracts/PredictionMarketV3.json +1 -0
- package/build/contracts/PredictionMarketV3Controller.json +1 -0
- package/build/contracts/PredictionMarketV3Factory.json +1 -0
- package/build/contracts/PredictionMarketV3Manager.json +1 -0
- package/build/contracts/PredictionMarketV3Querier.json +1 -0
- package/build/contracts/RealitioERC20.json +1 -0
- package/build/contracts/RealitioForeignArbitrationProxyWithAppeals.json +1 -0
- package/build/contracts/RealitioHomeArbitrationProxy.json +1 -0
- package/build/contracts/RealitioSafeMath256.json +1 -0
- package/build/contracts/RealitioSafeMath32.json +1 -0
- package/build/contracts/RealityETH_ERC20_Factory.json +1 -0
- package/build/contracts/RealityETH_ERC20_v3_0.json +1 -0
- package/build/contracts/ReentrancyGuard.json +1 -0
- package/build/contracts/SafeERC20.json +1 -0
- package/build/contracts/SafeMath.json +1 -0
- package/build/contracts/Strings.json +1 -0
- package/build/contracts/Voting.json +1 -0
- package/build/contracts/WETH9.json +1 -0
- package/build/contracts/test.json +1 -0
- package/cleanContracts.js +22 -0
- package/contracts/FantasyERC20.sol +81 -0
- package/contracts/IFantasyERC20.sol +20 -0
- package/contracts/IPredictionMarketV3.sol +207 -0
- package/contracts/IPredictionMarketV3Factory.sol +10 -0
- package/contracts/IPredictionMarketV3Manager.sol +12 -0
- package/contracts/IRealityETH_ERC20.sol +64 -0
- package/contracts/LandFactory.sol +248 -0
- package/contracts/Migrations.sol +24 -0
- package/contracts/PredictionMarketV3.sol +1332 -0
- package/contracts/PredictionMarketV3Controller.sol +87 -0
- package/contracts/PredictionMarketV3Factory.sol +205 -0
- package/contracts/PredictionMarketV3Manager.sol +45 -0
- package/contracts/PredictionMarketV3Querier.sol +79 -0
- package/contracts/RealityETH_ERC20_Factory.sol +54 -0
- package/contracts/Voting.sol +153 -0
- package/contracts/WETH9.sol +62 -0
- package/help.txt +8 -0
- package/index.js +3 -0
- package/migrations/10_deploy_weth.js +5 -0
- package/migrations/11_deploy_full_flow.js +99 -0
- package/migrations/12_deploy_pm_v3_querier.js +7 -0
- package/migrations/13_deploy_pm_v3_factory.js +14 -0
- package/migrations/1_initial_migration.js +5 -0
- package/migrations/2_deploy_erc20.js +10 -0
- package/migrations/3_deploy_realitio.js +11 -0
- package/migrations/4_deploy_pm.js +20 -0
- package/migrations/5_seed_markets.js +51 -0
- package/migrations/6_deploy_achievements.js +5 -0
- package/migrations/7_deploy_voting.js +14 -0
- package/migrations/8_deploy_pm_v2.js +20 -0
- package/migrations/9_seed_markets_v2.js +68 -0
- package/package.json +106 -13
- package/src/Application.js +421 -0
- package/src/interfaces/index.js +19 -0
- package/src/models/AchievementsContract.js +217 -0
- package/src/models/ArbitrationContract.js +69 -0
- package/src/models/ArbitrationProxyContract.js +32 -0
- package/src/models/ERC20Contract.js +156 -0
- package/src/models/FantasyERC20Contract.js +92 -0
- package/src/models/IContract.js +1002 -0
- package/src/models/PolkamarketsSmartAccount.js +100 -0
- package/src/models/PredictionMarketContract.js +562 -0
- package/src/models/PredictionMarketV2Contract.js +830 -0
- package/src/models/PredictionMarketV3Contract.js +233 -0
- package/src/models/PredictionMarketV3ControllerContract.js +102 -0
- package/src/models/PredictionMarketV3FactoryContract.js +96 -0
- package/src/models/PredictionMarketV3ManagerContract.js +111 -0
- package/src/models/PredictionMarketV3QuerierContract.js +24 -0
- package/src/models/RealitioERC20Contract.js +286 -0
- package/src/models/VotingContract.js +182 -0
- package/src/models/WETH9Contract.js +92 -0
- package/src/models/index.js +33 -0
- package/src/utils/Account.js +40 -0
- package/src/utils/Contract.js +120 -0
- package/src/utils/Numbers.js +94 -0
- package/tests/fantasyERC20Contract.js +225 -0
- package/tests/index.js +10 -0
- package/tests/predictionMarketContract.js +466 -0
- package/tests/predictionMarketV2Contract.js +1042 -0
- package/tests/predictionMarketV3Contract.js +1079 -0
- package/tests/predictionMarketV3ControllerContract.js +613 -0
- package/tests/predictionMarketV3FactoryContract.js +469 -0
- package/tests/predictionMarketV3ManagerContract.js +610 -0
- package/tests/utils.js +16 -0
- package/tests/votingContract.js +490 -0
- package/tooling/docs/jsdoc.json +6 -0
- package/truffle-config.js +134 -0
- package/polkamarkets.js +0 -422
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import moment from 'moment';
|
|
5
|
+
|
|
6
|
+
import { mochaAsync } from './utils';
|
|
7
|
+
import { Application } from '..';
|
|
8
|
+
|
|
9
|
+
context('Prediction Market Contract V3 Controller', async () => {
|
|
10
|
+
require('dotenv').config();
|
|
11
|
+
|
|
12
|
+
const TOKEN_AMOUNT_TO_CLAIM = 10;
|
|
13
|
+
const LOCK_AMOUNT = 5;
|
|
14
|
+
|
|
15
|
+
const USER1_ADDRESS = process.env.TEST_USER1_ADDRESS;
|
|
16
|
+
const USER1_PRIVATE_KEY = process.env.TEST_USER1_PRIVATE_KEY;
|
|
17
|
+
const USER2_ADDRESS = process.env.TEST_USER2_ADDRESS;
|
|
18
|
+
|
|
19
|
+
let app;
|
|
20
|
+
let accountAddress;
|
|
21
|
+
let predictionMarketContract;
|
|
22
|
+
let predictionMarketFactoryContract;
|
|
23
|
+
let predictionMarketControllerContract;
|
|
24
|
+
let realitioERC20Contract
|
|
25
|
+
let pmfTokenContract;
|
|
26
|
+
|
|
27
|
+
context('Contract Deployment', async () => {
|
|
28
|
+
it('should start the Application', mochaAsync(async () => {
|
|
29
|
+
app = new Application({
|
|
30
|
+
web3Provider: process.env.WEB3_PROVIDER,
|
|
31
|
+
web3PrivateKey: process.env.WEB3_PRIVATE_KEY
|
|
32
|
+
});
|
|
33
|
+
expect(app).to.not.equal(null);
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
it('should deploy Prediction Market Controller Contract', mochaAsync(async () => {
|
|
37
|
+
accountAddress = await app.getAddress();
|
|
38
|
+
|
|
39
|
+
// Create Contract
|
|
40
|
+
predictionMarketContract = app.getPredictionMarketV3Contract({});
|
|
41
|
+
pmfTokenContract = app.getERC20Contract({});
|
|
42
|
+
realitioERC20Contract = app.getRealitioERC20Contract({});
|
|
43
|
+
|
|
44
|
+
await realitioERC20Contract.deploy({});
|
|
45
|
+
|
|
46
|
+
// Deploy
|
|
47
|
+
await pmfTokenContract.deploy({ params: ['Polkamarkets', 'POLK'] });
|
|
48
|
+
const pmfTokenContractAddress = pmfTokenContract.getAddress();
|
|
49
|
+
|
|
50
|
+
predictionMarketFactoryContract = app.getPredictionMarketV3FactoryContract({});
|
|
51
|
+
// Deploy
|
|
52
|
+
await predictionMarketContract.deploy({
|
|
53
|
+
params: [
|
|
54
|
+
'0x0000000000000000000000000000000000000000'
|
|
55
|
+
]
|
|
56
|
+
});
|
|
57
|
+
const predictionMarketContractAddress = predictionMarketContract.getAddress();
|
|
58
|
+
|
|
59
|
+
await predictionMarketFactoryContract.deploy({
|
|
60
|
+
params:
|
|
61
|
+
[
|
|
62
|
+
pmfTokenContractAddress,
|
|
63
|
+
(LOCK_AMOUNT * 10 ** 18).toString(), // TODO: improve this
|
|
64
|
+
predictionMarketContractAddress,
|
|
65
|
+
realitioERC20Contract.getAddress()
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
const predictionMarketFactoryContractAddress = predictionMarketFactoryContract.getAddress();
|
|
69
|
+
|
|
70
|
+
await pmfTokenContract.mint({
|
|
71
|
+
address: accountAddress,
|
|
72
|
+
amount: '1000'
|
|
73
|
+
});
|
|
74
|
+
await pmfTokenContract.approve({
|
|
75
|
+
address: predictionMarketFactoryContractAddress,
|
|
76
|
+
amount: '1000000'
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
await predictionMarketFactoryContract.createPMController({
|
|
80
|
+
PMV3: predictionMarketContract.getAddress(),
|
|
81
|
+
WETH: '0x0000000000000000000000000000000000000000',
|
|
82
|
+
realitioLibraryAddress: realitioERC20Contract.getAddress(),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const predictionMarketControllerAddress = await predictionMarketFactoryContract.getPMControllerAddressById({
|
|
86
|
+
id: 0
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
expect(predictionMarketControllerAddress).to.not.equal(null);
|
|
90
|
+
|
|
91
|
+
predictionMarketControllerContract = app.getPredictionMarketV3ControllerContract({ contractAddress: predictionMarketControllerAddress });
|
|
92
|
+
|
|
93
|
+
expect(predictionMarketControllerContract).to.not.equal(null);
|
|
94
|
+
expect(predictionMarketContractAddress).to.not.equal(null);
|
|
95
|
+
expect(pmfTokenContractAddress).to.not.equal(null);
|
|
96
|
+
}));
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
context('Land Management', async () => {
|
|
100
|
+
context('Land Creation', async () => {
|
|
101
|
+
it('should create a Land', mochaAsync(async () => {
|
|
102
|
+
const currentLandIndex = await predictionMarketControllerContract.getLandTokensLength();
|
|
103
|
+
|
|
104
|
+
await predictionMarketControllerContract.createLand({
|
|
105
|
+
name: 'Token',
|
|
106
|
+
symbol: 'TOKEN',
|
|
107
|
+
tokenAmountToClaim: TOKEN_AMOUNT_TO_CLAIM,
|
|
108
|
+
tokenToAnswer: pmfTokenContract.getAddress(),
|
|
109
|
+
everyoneCanCreateMarkets: false
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const land = await predictionMarketControllerContract.getLandById({ id: currentLandIndex });
|
|
113
|
+
const newLandIndex = await predictionMarketControllerContract.getLandTokensLength();
|
|
114
|
+
|
|
115
|
+
expect(newLandIndex).to.equal(currentLandIndex + 1);
|
|
116
|
+
expect(land.token).to.not.equal('0x0000000000000000000000000000000000000000');
|
|
117
|
+
expect(land.active).to.equal(true);
|
|
118
|
+
expect(land.everyoneCanCreateMarkets).to.equal(false);
|
|
119
|
+
expect(land.realitio).to.not.equal('0x0000000000000000000000000000000000000000');
|
|
120
|
+
}));
|
|
121
|
+
|
|
122
|
+
it('should create another Land', mochaAsync(async () => {
|
|
123
|
+
const currentLandIndex = await predictionMarketControllerContract.getLandTokensLength();
|
|
124
|
+
|
|
125
|
+
await predictionMarketControllerContract.createLand({
|
|
126
|
+
name: 'Token 2',
|
|
127
|
+
symbol: 'TOKEN2',
|
|
128
|
+
tokenAmountToClaim: TOKEN_AMOUNT_TO_CLAIM,
|
|
129
|
+
tokenToAnswer: pmfTokenContract.getAddress(),
|
|
130
|
+
everyoneCanCreateMarkets: true
|
|
131
|
+
});
|
|
132
|
+
const land = await predictionMarketControllerContract.getLandById({ id: currentLandIndex });
|
|
133
|
+
const newLandIndex = await predictionMarketControllerContract.getLandTokensLength();
|
|
134
|
+
|
|
135
|
+
expect(newLandIndex).to.equal(currentLandIndex + 1);
|
|
136
|
+
expect(land.token).to.not.equal('0x0000000000000000000000000000000000000000');
|
|
137
|
+
expect(land.active).to.equal(true);
|
|
138
|
+
expect(land.everyoneCanCreateMarkets).to.equal(true);
|
|
139
|
+
expect(land.realitio).to.not.equal('0x0000000000000000000000000000000000000000');
|
|
140
|
+
}));
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
context('Land Admins', async () => {
|
|
144
|
+
let landId = 0;
|
|
145
|
+
let token;
|
|
146
|
+
|
|
147
|
+
const user1 = USER1_ADDRESS;
|
|
148
|
+
const user2 = USER2_ADDRESS;
|
|
149
|
+
|
|
150
|
+
let user1App;
|
|
151
|
+
let user1PredictionMarketControllerContract;
|
|
152
|
+
|
|
153
|
+
before(mochaAsync(async () => {
|
|
154
|
+
const land = await predictionMarketControllerContract.getLandById({ id: landId });
|
|
155
|
+
token = land.token;
|
|
156
|
+
|
|
157
|
+
user1App = new Application({
|
|
158
|
+
web3Provider: process.env.WEB3_PROVIDER,
|
|
159
|
+
web3PrivateKey: USER1_PRIVATE_KEY
|
|
160
|
+
});
|
|
161
|
+
user1PredictionMarketControllerContract = user1App.getPredictionMarketV3ControllerContract({
|
|
162
|
+
contractAddress: predictionMarketControllerContract.getAddress()
|
|
163
|
+
});
|
|
164
|
+
}));
|
|
165
|
+
|
|
166
|
+
it('should add an admin to a Land', mochaAsync(async () => {
|
|
167
|
+
const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
168
|
+
await predictionMarketControllerContract.addAdminToLand({
|
|
169
|
+
token,
|
|
170
|
+
user: user2
|
|
171
|
+
});
|
|
172
|
+
const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
173
|
+
|
|
174
|
+
expect(currentIsAdmin).to.equal(false);
|
|
175
|
+
expect(newIsAdmin).to.equal(true);
|
|
176
|
+
}));
|
|
177
|
+
|
|
178
|
+
it('should remove an admin from a Land', mochaAsync(async () => {
|
|
179
|
+
const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
180
|
+
await predictionMarketControllerContract.removeAdminFromLand({
|
|
181
|
+
token,
|
|
182
|
+
user: user2
|
|
183
|
+
});
|
|
184
|
+
const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
185
|
+
|
|
186
|
+
expect(currentIsAdmin).to.equal(true);
|
|
187
|
+
expect(newIsAdmin).to.equal(false);
|
|
188
|
+
}));
|
|
189
|
+
|
|
190
|
+
it('should not be able to add an admin to a Land if not an admin making the call', mochaAsync(async () => {
|
|
191
|
+
const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
192
|
+
try {
|
|
193
|
+
await user1PredictionMarketControllerContract.addAdminToLand({
|
|
194
|
+
token,
|
|
195
|
+
user: user2
|
|
196
|
+
});
|
|
197
|
+
} catch(e) {
|
|
198
|
+
// not logging error, as tx is expected to fail
|
|
199
|
+
}
|
|
200
|
+
const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
201
|
+
|
|
202
|
+
expect(currentIsAdmin).to.equal(false);
|
|
203
|
+
expect(newIsAdmin).to.equal(false);
|
|
204
|
+
}));
|
|
205
|
+
|
|
206
|
+
it('should be able to add/remove an admin to a Land after being made admin', mochaAsync(async () => {
|
|
207
|
+
await predictionMarketControllerContract.addAdminToLand({
|
|
208
|
+
token,
|
|
209
|
+
user: user1
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
213
|
+
await user1PredictionMarketControllerContract.addAdminToLand({
|
|
214
|
+
token,
|
|
215
|
+
user: user2
|
|
216
|
+
});
|
|
217
|
+
const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
218
|
+
|
|
219
|
+
expect(currentIsAdmin).to.equal(false);
|
|
220
|
+
expect(newIsAdmin).to.equal(true);
|
|
221
|
+
|
|
222
|
+
await user1PredictionMarketControllerContract.removeAdminFromLand({
|
|
223
|
+
token,
|
|
224
|
+
user: user2
|
|
225
|
+
});
|
|
226
|
+
const lastNewIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
227
|
+
|
|
228
|
+
expect(lastNewIsAdmin).to.equal(false);
|
|
229
|
+
|
|
230
|
+
// resetting user1 admin status
|
|
231
|
+
await predictionMarketControllerContract.removeAdminFromLand({
|
|
232
|
+
token,
|
|
233
|
+
user: user1
|
|
234
|
+
});
|
|
235
|
+
}));
|
|
236
|
+
|
|
237
|
+
it ('should be land admin if is a controller admin', mochaAsync(async () => {
|
|
238
|
+
const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user1 });
|
|
239
|
+
expect(currentIsAdmin).to.equal(false);
|
|
240
|
+
|
|
241
|
+
await predictionMarketFactoryContract.addAdminToPMController({
|
|
242
|
+
controllerAddress: predictionMarketControllerContract.getAddress(),
|
|
243
|
+
user: user1
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user1 });
|
|
247
|
+
expect(newIsAdmin).to.equal(true);
|
|
248
|
+
|
|
249
|
+
// new admin should be able to add another admin to a land
|
|
250
|
+
await user1PredictionMarketControllerContract.addAdminToLand({
|
|
251
|
+
token,
|
|
252
|
+
user: user2
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const user2IsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
256
|
+
expect(user2IsAdmin).to.equal(true);
|
|
257
|
+
|
|
258
|
+
// removing user2 as admin
|
|
259
|
+
await user1PredictionMarketControllerContract.removeAdminFromLand({
|
|
260
|
+
token,
|
|
261
|
+
user: user2
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
const user2IsAdminAfter = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
|
|
265
|
+
expect(user2IsAdminAfter).to.equal(false);
|
|
266
|
+
|
|
267
|
+
await predictionMarketFactoryContract.removeAdminFromPMController({
|
|
268
|
+
controllerAddress: predictionMarketControllerContract.getAddress(),
|
|
269
|
+
user: user1
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const lastNewIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user1 });
|
|
273
|
+
expect(lastNewIsAdmin).to.equal(false);
|
|
274
|
+
}));
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
context('Land Disabling + Enabling + Offset', async () => {
|
|
278
|
+
let landId = 0;
|
|
279
|
+
let land;
|
|
280
|
+
let token;
|
|
281
|
+
|
|
282
|
+
let user1App;
|
|
283
|
+
let user1PredictionMarketControllerContract;
|
|
284
|
+
|
|
285
|
+
let landTokenContract;
|
|
286
|
+
|
|
287
|
+
before(mochaAsync(async () => {
|
|
288
|
+
land = await predictionMarketControllerContract.getLandById({ id: landId });
|
|
289
|
+
landTokenContract = app.getFantasyERC20Contract({contractAddress: land.token});
|
|
290
|
+
token = land.token;
|
|
291
|
+
|
|
292
|
+
user1App = new Application({
|
|
293
|
+
web3Provider: process.env.WEB3_PROVIDER,
|
|
294
|
+
web3PrivateKey: USER1_PRIVATE_KEY
|
|
295
|
+
});
|
|
296
|
+
user1PredictionMarketControllerContract = user1App.getPredictionMarketV3ControllerContract({
|
|
297
|
+
contractAddress: predictionMarketControllerContract.getAddress()
|
|
298
|
+
});
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
it('should not be able to disable a Land if not an admin making the call', mochaAsync(async () => {
|
|
302
|
+
try {
|
|
303
|
+
await user1PredictionMarketControllerContract.disableLand({
|
|
304
|
+
token
|
|
305
|
+
});
|
|
306
|
+
} catch(e) {
|
|
307
|
+
// not logging error, as tx is expected to fail
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
|
|
311
|
+
|
|
312
|
+
expect(land.active).to.equal(true);
|
|
313
|
+
expect(refreshedLand.active).to.equal(true);
|
|
314
|
+
}));
|
|
315
|
+
|
|
316
|
+
it('should disable a Land', mochaAsync(async () => {
|
|
317
|
+
const currentPaused = await landTokenContract.paused();
|
|
318
|
+
await predictionMarketControllerContract.disableLand({
|
|
319
|
+
token: land.token
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
|
|
323
|
+
const newPaused = await landTokenContract.paused();
|
|
324
|
+
|
|
325
|
+
expect(land.active).to.equal(true);
|
|
326
|
+
expect(currentPaused).to.equal(false);
|
|
327
|
+
expect(newPaused).to.equal(true);
|
|
328
|
+
expect(refreshedLand.token).to.equal(land.token);
|
|
329
|
+
expect(refreshedLand.active).to.equal(false);
|
|
330
|
+
expect(refreshedLand.realitio).to.equal(land.realitio);
|
|
331
|
+
}));
|
|
332
|
+
|
|
333
|
+
it('should not be able to disable a Land if already disabled', mochaAsync(async () => {
|
|
334
|
+
try {
|
|
335
|
+
await predictionMarketControllerContract.disableLand({
|
|
336
|
+
token
|
|
337
|
+
});
|
|
338
|
+
} catch(e) {
|
|
339
|
+
// not logging error, as tx is expected to fail
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
|
|
343
|
+
|
|
344
|
+
expect(refreshedLand.active).to.equal(false);
|
|
345
|
+
}));
|
|
346
|
+
|
|
347
|
+
it('should enable a Land', mochaAsync(async () => {
|
|
348
|
+
const currentPaused = await landTokenContract.paused();
|
|
349
|
+
await predictionMarketControllerContract.enableLand({
|
|
350
|
+
token: land.token
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
|
|
354
|
+
const newPaused = await landTokenContract.paused();
|
|
355
|
+
|
|
356
|
+
expect(currentPaused).to.equal(true);
|
|
357
|
+
expect(newPaused).to.equal(false);
|
|
358
|
+
expect(refreshedLand.token).to.equal(land.token);
|
|
359
|
+
expect(refreshedLand.active).to.equal(true);
|
|
360
|
+
expect(refreshedLand.realitio).to.equal(land.realitio);
|
|
361
|
+
}));
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
context('Land Markets', async () => {
|
|
366
|
+
let landId = 0;
|
|
367
|
+
let marketId = 0;
|
|
368
|
+
let outcomeId = 0;
|
|
369
|
+
let value = 0.01;
|
|
370
|
+
let land;
|
|
371
|
+
let land2;
|
|
372
|
+
|
|
373
|
+
let user1;
|
|
374
|
+
let user1App;
|
|
375
|
+
let user1PredictionMarketContract;
|
|
376
|
+
|
|
377
|
+
let landTokenContract;
|
|
378
|
+
let land2TokenContract;
|
|
379
|
+
let user1LandTokenContract;
|
|
380
|
+
let user1Land2TokenContract;
|
|
381
|
+
|
|
382
|
+
before(mochaAsync(async () => {
|
|
383
|
+
land = await predictionMarketControllerContract.getLandById({ id: landId });
|
|
384
|
+
land2 = await predictionMarketControllerContract.getLandById({ id: landId + 1});
|
|
385
|
+
|
|
386
|
+
user1 = USER1_ADDRESS;
|
|
387
|
+
user1App = new Application({
|
|
388
|
+
web3Provider: process.env.WEB3_PROVIDER,
|
|
389
|
+
web3PrivateKey: USER1_PRIVATE_KEY
|
|
390
|
+
});
|
|
391
|
+
user1PredictionMarketContract = user1App.getPredictionMarketV3Contract({
|
|
392
|
+
contractAddress: predictionMarketContract.getAddress()
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
landTokenContract = app.getFantasyERC20Contract({contractAddress: land.token});
|
|
396
|
+
land2TokenContract = app.getFantasyERC20Contract({contractAddress: land2.token});
|
|
397
|
+
user1LandTokenContract = user1App.getFantasyERC20Contract({contractAddress: land.token});
|
|
398
|
+
user1Land2TokenContract = user1App.getFantasyERC20Contract({contractAddress: land2.token});
|
|
399
|
+
// approving land token to spend tokens
|
|
400
|
+
await landTokenContract.claimAndApproveTokens();
|
|
401
|
+
await land2TokenContract.claimAndApproveTokens();
|
|
402
|
+
await user1LandTokenContract.claimAndApproveTokens();
|
|
403
|
+
await user1Land2TokenContract.claimAndApproveTokens();
|
|
404
|
+
}));
|
|
405
|
+
|
|
406
|
+
context('Market Creation', async () => {
|
|
407
|
+
it('should not be able to create a Market if not an admin making the call and everyoneCanCreateMarkets is not active', mochaAsync(async () => {
|
|
408
|
+
const currentMarketIds = await predictionMarketContract.getMarkets();
|
|
409
|
+
const currentLandTokenBalance = await landTokenContract.balanceOf({ address: user1 });
|
|
410
|
+
expect(currentLandTokenBalance).to.equal(TOKEN_AMOUNT_TO_CLAIM);
|
|
411
|
+
expect(land.everyoneCanCreateMarkets).to.equal(false);
|
|
412
|
+
|
|
413
|
+
try {
|
|
414
|
+
await user1PredictionMarketContract.mintAndCreateMarket({
|
|
415
|
+
value,
|
|
416
|
+
name: 'Will BTC price close above 100k$ on May 1st 2025',
|
|
417
|
+
description: 'This is a description',
|
|
418
|
+
image: 'foo-bar',
|
|
419
|
+
category: 'Foo;Bar',
|
|
420
|
+
oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
|
|
421
|
+
duration: moment('2025-05-01').unix(),
|
|
422
|
+
outcomes: ['Yes', 'No'],
|
|
423
|
+
token: landTokenContract.getAddress(),
|
|
424
|
+
realitioAddress: land.realitio,
|
|
425
|
+
realitioTimeout: 300,
|
|
426
|
+
PM3ManagerAddress: predictionMarketControllerContract.getAddress()
|
|
427
|
+
});
|
|
428
|
+
} catch(e) {
|
|
429
|
+
// not logging error, as tx is expected to fail
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const newMarketIds = await predictionMarketContract.getMarkets();
|
|
433
|
+
expect(newMarketIds.length).to.equal(currentMarketIds.length);
|
|
434
|
+
}));
|
|
435
|
+
|
|
436
|
+
it('should create a Market if admin', mochaAsync(async () => {
|
|
437
|
+
const currentMarketIds = await predictionMarketContract.getMarkets();
|
|
438
|
+
const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
439
|
+
expect(currentLandTokenBalance).to.equal(TOKEN_AMOUNT_TO_CLAIM);
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
const res = await predictionMarketContract.mintAndCreateMarket({
|
|
443
|
+
value,
|
|
444
|
+
name: 'Will BTC price close above 100k$ on May 1st 2025',
|
|
445
|
+
description: 'This is a description',
|
|
446
|
+
image: 'foo-bar',
|
|
447
|
+
category: 'Foo;Bar',
|
|
448
|
+
oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
|
|
449
|
+
duration: moment('2025-05-01').unix(),
|
|
450
|
+
outcomes: ['Yes', 'No'],
|
|
451
|
+
token: landTokenContract.getAddress(),
|
|
452
|
+
realitioAddress: land.realitio,
|
|
453
|
+
realitioTimeout: 300,
|
|
454
|
+
PM3ManagerAddress: predictionMarketControllerContract.getAddress()
|
|
455
|
+
});
|
|
456
|
+
expect(res.status).to.equal(true);
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
460
|
+
const newMarketIds = await predictionMarketContract.getMarkets();
|
|
461
|
+
expect(newMarketIds.length).to.equal(currentMarketIds.length + 1);
|
|
462
|
+
// balance remains the same since tokens were minted
|
|
463
|
+
expect(newLandTokenBalance).to.equal(currentLandTokenBalance);
|
|
464
|
+
}));
|
|
465
|
+
|
|
466
|
+
it('should be able to create a Market if not an admin making the call and everyoneCanCreateMarkets is active', mochaAsync(async () => {
|
|
467
|
+
const currentMarketIds = await predictionMarketContract.getMarkets();
|
|
468
|
+
const currentLandTokenBalance = await land2TokenContract.balanceOf({ address: user1 });
|
|
469
|
+
expect(currentLandTokenBalance).to.equal(TOKEN_AMOUNT_TO_CLAIM);
|
|
470
|
+
expect(await predictionMarketControllerContract.isLandAdmin({ token: land2TokenContract.getAddress(), user: user1 })).to.equal(false);
|
|
471
|
+
expect(land2.everyoneCanCreateMarkets).to.equal(true);
|
|
472
|
+
|
|
473
|
+
const res = await predictionMarketContract.mintAndCreateMarket({
|
|
474
|
+
value,
|
|
475
|
+
name: 'Will Something Happen tomorrow?',
|
|
476
|
+
description: 'This is a description',
|
|
477
|
+
image: 'foo-bar',
|
|
478
|
+
category: 'Foo;Bar',
|
|
479
|
+
oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
|
|
480
|
+
duration: moment('2026-05-01').unix(),
|
|
481
|
+
outcomes: ['Yes', 'No'],
|
|
482
|
+
token: land2TokenContract.getAddress(),
|
|
483
|
+
realitioAddress: land2.realitio,
|
|
484
|
+
realitioTimeout: 300,
|
|
485
|
+
PM3ManagerAddress: predictionMarketControllerContract.getAddress()
|
|
486
|
+
});
|
|
487
|
+
expect(res.status).to.equal(true);
|
|
488
|
+
|
|
489
|
+
const newLandTokenBalance = await land2TokenContract.balanceOf({ address: accountAddress });
|
|
490
|
+
const newMarketIds = await predictionMarketContract.getMarkets();
|
|
491
|
+
expect(newMarketIds.length).to.equal(currentMarketIds.length + 1);
|
|
492
|
+
// balance remains the same since tokens were minted
|
|
493
|
+
expect(newLandTokenBalance).to.equal(currentLandTokenBalance);
|
|
494
|
+
}));
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
context('Market Interaction', async () => {
|
|
498
|
+
it('should be able to buy shares when land enabled', mochaAsync(async () => {
|
|
499
|
+
const minOutcomeSharesToBuy = 0.015;
|
|
500
|
+
const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
501
|
+
|
|
502
|
+
try {
|
|
503
|
+
const res = await predictionMarketContract.buy({marketId, outcomeId, value, minOutcomeSharesToBuy});
|
|
504
|
+
expect(res.status).to.equal(true);
|
|
505
|
+
} catch(e) {
|
|
506
|
+
console.log(e);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
510
|
+
const amountTransferred = Number((currentLandTokenBalance - newLandTokenBalance).toFixed(5));
|
|
511
|
+
|
|
512
|
+
expect(amountTransferred).to.equal(value);
|
|
513
|
+
}));
|
|
514
|
+
|
|
515
|
+
it('should sell outcome shares', mochaAsync(async () => {
|
|
516
|
+
const outcomeId = 0;
|
|
517
|
+
const maxOutcomeSharesToSell = 0.015;
|
|
518
|
+
|
|
519
|
+
const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
const res = await predictionMarketContract.sell({marketId, outcomeId, value, maxOutcomeSharesToSell});
|
|
523
|
+
expect(res.status).to.equal(true);
|
|
524
|
+
} catch(e) {
|
|
525
|
+
console.log(e);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
529
|
+
const amountTransferred = Number((newLandTokenBalance - currentLandTokenBalance).toFixed(5));
|
|
530
|
+
|
|
531
|
+
expect(amountTransferred).to.equal(value);
|
|
532
|
+
}));
|
|
533
|
+
|
|
534
|
+
it('should not be able to buy shares when land disabled', mochaAsync(async () => {
|
|
535
|
+
const minOutcomeSharesToBuy = 0.015;
|
|
536
|
+
const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
537
|
+
|
|
538
|
+
await predictionMarketControllerContract.disableLand({
|
|
539
|
+
token: land.token
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
try {
|
|
543
|
+
const res = await predictionMarketContract.buy({marketId, outcomeId, value, minOutcomeSharesToBuy});
|
|
544
|
+
expect(res.status).to.equal(true);
|
|
545
|
+
} catch(e) {
|
|
546
|
+
// not logging error, as tx is expected to fail
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
550
|
+
const amountTransferred = currentLandTokenBalance - newLandTokenBalance;
|
|
551
|
+
|
|
552
|
+
expect(amountTransferred).to.equal(0);
|
|
553
|
+
}));
|
|
554
|
+
|
|
555
|
+
it('should be able to buy shares when land enabled again', mochaAsync(async () => {
|
|
556
|
+
const minOutcomeSharesToBuy = 0.015;
|
|
557
|
+
const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
558
|
+
|
|
559
|
+
await predictionMarketControllerContract.enableLand({
|
|
560
|
+
token: land.token
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
try {
|
|
564
|
+
const res = await predictionMarketContract.buy({marketId, outcomeId, value, minOutcomeSharesToBuy});
|
|
565
|
+
expect(res.status).to.equal(true);
|
|
566
|
+
} catch(e) {
|
|
567
|
+
console.log(e);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
|
|
571
|
+
const amountTransferred = Number((currentLandTokenBalance - newLandTokenBalance).toFixed(5));
|
|
572
|
+
|
|
573
|
+
expect(amountTransferred).to.equal(value);
|
|
574
|
+
}));
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
context('Market Resolution', async () => {
|
|
578
|
+
let outcomeId = 1;
|
|
579
|
+
|
|
580
|
+
it('should not be able to resolve a Market if not an admin making the call', mochaAsync(async () => {
|
|
581
|
+
try {
|
|
582
|
+
await user1PredictionMarketContract.adminResolveMarketOutcome({
|
|
583
|
+
marketId,
|
|
584
|
+
outcomeId
|
|
585
|
+
});
|
|
586
|
+
} catch(e) {
|
|
587
|
+
// not logging error, as tx is expected to fail
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const market = await predictionMarketContract.getMarketData({ marketId });
|
|
591
|
+
expect(market.state).to.equal(0);
|
|
592
|
+
}));
|
|
593
|
+
|
|
594
|
+
it('should be able to resolve a Market', mochaAsync(async () => {
|
|
595
|
+
try {
|
|
596
|
+
const res = await predictionMarketContract.adminResolveMarketOutcome({
|
|
597
|
+
marketId,
|
|
598
|
+
outcomeId
|
|
599
|
+
});
|
|
600
|
+
expect(res.status).to.equal(true);
|
|
601
|
+
} catch(e) {
|
|
602
|
+
console.log(e);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// doing dummy transaction to get the latest block
|
|
606
|
+
await landTokenContract.approve({ address: '0x000000000000000000000000000000000000dead', amount: 0 });
|
|
607
|
+
|
|
608
|
+
const market = await predictionMarketContract.getMarketData({ marketId });
|
|
609
|
+
expect(market.state).to.equal(2);
|
|
610
|
+
}));
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
});
|