Skip to content

Commit 428d469

Browse files
Migrate Fullchain tests to Hardhat and convert them to full integration tests (#156)
2 parents 825209a + f231b9d commit 428d469

File tree

7 files changed

+314
-107
lines changed

7 files changed

+314
-107
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## vNEXT
44

5+
- Migrate integration test files to Typescript & Hardhat:
6+
- 000_fullchain.js (#155)
57
- Remove `smock` from unit tests:
68
- IexecEscrow.v8 (#154, #155)
79
- IexecPocoDelegate (#149, #151)

test/000_fullchain.test.ts

Lines changed: 169 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,54 +3,68 @@
33

44
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
55
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
6-
import { TypedDataDomain } from 'ethers';
7-
import hre, { ethers, expect } from 'hardhat';
6+
import { ethers, expect } from 'hardhat';
87
import { loadHardhatFixtureDeployment } from '../scripts/hardhat-fixture-deployer';
9-
import { IexecAccessors, IexecAccessors__factory, IexecPocoAccessors__factory } from '../typechain';
10-
import { IexecPoco1 } from '../typechain/contracts/modules/interfaces/IexecPoco1.v8.sol';
11-
import { IexecPoco1__factory } from '../typechain/factories/contracts/modules/interfaces/IexecPoco1.v8.sol';
8+
import {
9+
IexecInterfaceNative,
10+
IexecInterfaceNative__factory,
11+
IexecPocoAccessors__factory,
12+
} from '../typechain';
1213
import {
1314
OrdersActors,
1415
OrdersAssets,
1516
OrdersPrices,
1617
buildOrders,
1718
signOrders,
1819
} from '../utils/createOrders';
19-
import { getDealId, getIexecAccounts } from '../utils/poco-tools';
20+
import {
21+
PocoMode,
22+
TaskStatusEnum,
23+
buildResultCallbackAndDigest,
24+
buildUtf8ResultAndDigest,
25+
getDealId,
26+
getIexecAccounts,
27+
} from '../utils/poco-tools';
2028
import { IexecWrapper } from './utils/IexecWrapper';
2129

30+
// +---------+-------------+-------------+-------------+----------+-----+----------------+
31+
// | | Sponsorship | Replication | Beneficiary | Callback | BoT | Type |
32+
// +---------+-------------+-------------+-------------+----------+-----+----------------+
33+
// | [1] | ✔ | ✔ | ✔ | ✔ | ✔ | Standard |
34+
// | [2] | x | ✔ | ✔ | ✔ | ✔ | Standard |
35+
// | [3] | ✔ | x | ✔ | ✔ | ✔ | Standard,TEE |
36+
// | [4] | x | x | ✔ | ✔ | ✔ | Standard,TEE |
37+
// | [5] | x | x | x | x | x | Standard,TEE |
38+
// +---------+-------------+-------------+----------+-----+-------------+----------------+
39+
40+
const standardDealTag = '0x0000000000000000000000000000000000000000000000000000000000000000';
2241
const teeDealTag = '0x0000000000000000000000000000000000000000000000000000000000000001';
23-
const taskIndex = 0;
24-
const volume = taskIndex + 1;
2542
const appPrice = 1000;
2643
const datasetPrice = 1_000_000;
2744
const workerpoolPrice = 1_000_000_000;
45+
const callbackAddress = ethers.Wallet.createRandom().address;
46+
const { results } = buildUtf8ResultAndDigest('result');
47+
const { resultsCallback, callbackResultDigest } = buildResultCallbackAndDigest(123);
2848

29-
/*
30-
* TODO make this a real integration test (match, contribute, ..., finalize).
31-
*/
32-
33-
describe('IexecPoco (IT)', function () {
34-
let domain: TypedDataDomain;
35-
let proxyAddress: string;
36-
let iexecAccessor: IexecAccessors;
37-
let iexecPoco: IexecPoco1;
38-
let iexecWrapper: IexecWrapper;
39-
let [appAddress, workerpoolAddress, datasetAddress]: string[] = [];
40-
let [
41-
iexecAdmin,
42-
requester,
43-
sponsor,
44-
beneficiary,
45-
appProvider,
46-
datasetProvider,
47-
scheduler,
48-
anyone,
49-
]: SignerWithAddress[] = [];
50-
let ordersActors: OrdersActors;
51-
let ordersAssets: OrdersAssets;
52-
let ordersPrices: OrdersPrices;
49+
let proxyAddress: string;
50+
let iexecPoco: IexecInterfaceNative;
51+
let iexecWrapper: IexecWrapper;
52+
let [appAddress, workerpoolAddress, datasetAddress]: string[] = [];
53+
let [
54+
requester,
55+
sponsor,
56+
beneficiary,
57+
appProvider,
58+
datasetProvider,
59+
scheduler,
60+
anyone,
61+
worker1,
62+
]: SignerWithAddress[] = [];
63+
let ordersActors: OrdersActors;
64+
let ordersAssets: OrdersAssets;
65+
let ordersPrices: OrdersPrices;
5366

67+
describe('Integration tests', function () {
5468
beforeEach('Deploy', async () => {
5569
// Deploy all contracts
5670
proxyAddress = await loadHardhatFixtureDeployment();
@@ -61,32 +75,24 @@ describe('IexecPoco (IT)', function () {
6175
async function initFixture() {
6276
const accounts = await getIexecAccounts();
6377
({
64-
iexecAdmin,
6578
requester,
6679
sponsor,
6780
beneficiary,
6881
appProvider,
6982
datasetProvider,
7083
scheduler,
7184
anyone,
85+
worker1,
7286
} = accounts);
7387
iexecWrapper = new IexecWrapper(proxyAddress, accounts);
7488
({ appAddress, datasetAddress, workerpoolAddress } = await iexecWrapper.createAssets());
75-
await iexecWrapper.setTeeBroker('0x0000000000000000000000000000000000000000');
76-
iexecPoco = IexecPoco1__factory.connect(proxyAddress, iexecAdmin);
77-
iexecAccessor = IexecAccessors__factory.connect(proxyAddress, anyone);
89+
iexecPoco = IexecInterfaceNative__factory.connect(proxyAddress, anyone);
7890
ordersActors = {
7991
appOwner: appProvider,
8092
datasetOwner: datasetProvider,
8193
workerpoolOwner: scheduler,
8294
requester: requester,
8395
};
84-
domain = {
85-
name: 'iExecODB',
86-
version: '5.0.0',
87-
chainId: hre.network.config.chainId,
88-
verifyingContract: proxyAddress,
89-
};
9096
ordersAssets = {
9197
app: appAddress,
9298
dataset: datasetAddress,
@@ -99,7 +105,112 @@ describe('IexecPoco (IT)', function () {
99105
};
100106
}
101107

102-
describe('MatchOrders', function () {
108+
it('[1] Sponsorship, beneficiary, callback, BoT, replication', async function () {
109+
const volume = 3;
110+
// Create deal.
111+
const orders = buildOrders({
112+
assets: ordersAssets,
113+
prices: ordersPrices,
114+
requester: requester.address,
115+
tag: standardDealTag,
116+
beneficiary: beneficiary.address,
117+
callback: callbackAddress,
118+
volume,
119+
trust: 1, // TODO use 5 workers.
120+
});
121+
const { dealId, dealPrice, schedulerStakePerDeal } =
122+
await iexecWrapper.signAndSponsorMatchOrders(...orders.toArray());
123+
const taskPrice = appPrice + datasetPrice + workerpoolPrice;
124+
const schedulerStakePerTask = schedulerStakePerDeal / volume;
125+
const workerRewardPerTask = await iexecWrapper.computeWorkerRewardPerTask(
126+
dealId,
127+
PocoMode.CLASSIC,
128+
);
129+
const schedulerRewardPerTask = workerpoolPrice - workerRewardPerTask;
130+
// Check initial balances.
131+
// TODO save initial balances and use them in for loop for comparison.
132+
await checkBalancesAndFrozens({
133+
proxyBalance: dealPrice + schedulerStakePerDeal,
134+
accounts: [
135+
{ signer: sponsor, balance: 0, frozen: dealPrice },
136+
{ signer: requester, balance: 0, frozen: 0 },
137+
{ signer: scheduler, balance: 0, frozen: schedulerStakePerDeal },
138+
{ signer: appProvider, balance: 0, frozen: 0 },
139+
{ signer: datasetProvider, balance: 0, frozen: 0 },
140+
{ signer: worker1, balance: 0, frozen: 0 },
141+
],
142+
});
143+
// Finalize each task and check balance changes.
144+
for (let taskIndex = 0; taskIndex < volume; taskIndex++) {
145+
const taskId = await iexecWrapper.initializeTask(dealId, taskIndex);
146+
const { workerStakePerTask } = await iexecWrapper.contributeToTask(
147+
dealId,
148+
taskIndex,
149+
callbackResultDigest,
150+
worker1,
151+
);
152+
await iexecPoco
153+
.connect(worker1)
154+
.reveal(taskId, callbackResultDigest)
155+
.then((tx) => tx.wait());
156+
await iexecPoco
157+
.connect(scheduler)
158+
.finalize(taskId, results, resultsCallback)
159+
.then((tx) => tx.wait());
160+
expect((await iexecPoco.viewTask(taskId)).status).to.equal(TaskStatusEnum.COMPLETED);
161+
// Multiply amount by the number of finalized tasks to correctly compute
162+
// stake and reward amounts.
163+
const completedTasks = taskIndex + 1;
164+
// For each task, balances change such as:
165+
// - Sponsor
166+
// - frozen: frozenBefore - taskPrice
167+
// - Requester: no changes
168+
// - Scheduler
169+
// - balance: balanceBefore + taskStake + taskReward
170+
// - frozen: frozenBefore - taskStake
171+
// - App
172+
// - balance: balance before + appPrice
173+
// - Dataset
174+
// - balance: balance before + datasetPrice
175+
// - Worker:
176+
// - balance: balance before + taskStake + taskReward
177+
// - frozen: frozen before - taskStake
178+
await checkBalancesAndFrozens({
179+
proxyBalance:
180+
dealPrice +
181+
schedulerStakePerDeal -
182+
(taskPrice + schedulerStakePerTask) * completedTasks,
183+
accounts: [
184+
{ signer: sponsor, balance: 0, frozen: dealPrice - taskPrice * completedTasks },
185+
{ signer: requester, balance: 0, frozen: 0 },
186+
{
187+
signer: scheduler,
188+
balance: (schedulerStakePerTask + schedulerRewardPerTask) * completedTasks,
189+
frozen: schedulerStakePerDeal - schedulerStakePerTask * completedTasks,
190+
},
191+
{ signer: appProvider, balance: appPrice * completedTasks, frozen: 0 },
192+
{ signer: datasetProvider, balance: datasetPrice * completedTasks, frozen: 0 },
193+
{
194+
signer: worker1,
195+
balance: (workerStakePerTask + workerRewardPerTask) * completedTasks,
196+
frozen: 0,
197+
},
198+
],
199+
});
200+
}
201+
});
202+
203+
// TODO implement the following tests.
204+
205+
it('[2] No sponsorship, beneficiary, callback, BoT, replication', async function () {});
206+
207+
it('[3] Sponsorship, beneficiary, callback, BoT, no replication', async function () {});
208+
209+
it('[4] No sponsorship, beneficiary, callback, BoT, no replication', async function () {});
210+
211+
it('[5] No sponsorship, no beneficiary, no callback, no BoT, no replication', async function () {});
212+
213+
describe.skip('MatchOrders', function () {
103214
it('Should sponsor match orders (TEE)', async function () {
104215
const callbackAddress = ethers.Wallet.createRandom().address;
105216
const orders = buildOrders({
@@ -166,3 +277,18 @@ describe('IexecPoco (IT)', function () {
166277
});
167278
});
168279
});
280+
281+
async function checkBalancesAndFrozens(args: {
282+
proxyBalance: number;
283+
accounts: { signer: SignerWithAddress; balance: number; frozen: number }[];
284+
}) {
285+
expect(await iexecPoco.balanceOf(proxyAddress)).to.equal(args.proxyBalance);
286+
for (const account of args.accounts) {
287+
const message = `Failed with account at index ${args.accounts.indexOf(account)}`;
288+
expect(await iexecPoco.balanceOf(account.signer.address)).to.equal(
289+
account.balance,
290+
message,
291+
);
292+
expect(await iexecPoco.frozenOf(account.signer.address)).to.equal(account.frozen, message);
293+
}
294+
}

test/byContract/IexecAccessors/IexecAccessors.test.ts

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH <[email protected]>
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { AddressZero, HashZero } from '@ethersproject/constants';
4+
import { HashZero } from '@ethersproject/constants';
55
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
66
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
77
import { deployments, ethers, expect } from 'hardhat';
@@ -14,9 +14,7 @@ import {
1414
import { OrdersAssets, buildOrders } from '../../../utils/createOrders';
1515
import {
1616
TaskStatusEnum,
17-
buildAndSignContributionAuthorizationMessage,
1817
buildResultCallbackAndDigest,
19-
buildResultHashAndResultSeal,
2018
buildUtf8ResultAndDigest,
2119
getIexecAccounts,
2220
getTaskId,
@@ -87,7 +85,7 @@ describe('IexecAccessors', async () => {
8785

8886
it('viewTask', async function () {
8987
const { dealId, taskId, taskIndex, startTime, timeRef } = await createDeal();
90-
await initializeTask(dealId, taskIndex);
88+
await iexecWrapper.initializeTask(dealId, taskIndex);
9189

9290
const contributionDeadlineRatio = (
9391
await iexecPoco.contribution_deadline_ratio()
@@ -186,9 +184,11 @@ describe('IexecAccessors', async () => {
186184
it('Should get result of task', async function () {
187185
const { dealId, taskId, taskIndex } = await createDeal();
188186

189-
await initializeTask(dealId, taskIndex).then(() =>
190-
contributeToTask(dealId, taskIndex, callbackResultDigest),
191-
);
187+
await iexecWrapper
188+
.initializeTask(dealId, taskIndex)
189+
.then(() =>
190+
iexecWrapper.contributeToTask(dealId, taskIndex, callbackResultDigest, worker1),
191+
);
192192
await iexecPoco
193193
.connect(worker1)
194194
.reveal(taskId, callbackResultDigest)
@@ -206,10 +206,10 @@ describe('IexecAccessors', async () => {
206206
const { dealId } = await createDeal(3);
207207

208208
const unsetTaskId = getTaskId(dealId, 0);
209-
const activeTaskId = await initializeTask(dealId, 1);
210-
const revealingTaskId = await initializeTask(dealId, 2).then(() =>
211-
contributeToTask(dealId, 2, resultDigest),
212-
);
209+
const activeTaskId = await iexecWrapper.initializeTask(dealId, 1);
210+
const { taskId: revealingTaskId } = await iexecWrapper
211+
.initializeTask(dealId, 2)
212+
.then(() => iexecWrapper.contributeToTask(dealId, 2, resultDigest, worker1));
213213

214214
await verifyTaskStatusAndResult(unsetTaskId, TaskStatusEnum.UNSET);
215215
await verifyTaskStatusAndResult(activeTaskId, TaskStatusEnum.ACTIVE);
@@ -236,37 +236,6 @@ async function createDeal(volume: number = 1) {
236236
return { dealId, taskId, taskIndex, startTime, timeRef };
237237
}
238238

239-
/**
240-
* Helper function to initialize a task.
241-
*/
242-
async function initializeTask(dealId: string, taskIndex: number) {
243-
await iexecPoco.initialize(dealId, taskIndex).then((tx) => tx.wait());
244-
return getTaskId(dealId, taskIndex);
245-
}
246-
247-
/**
248-
* Helper function to contribute to a task.
249-
*/
250-
async function contributeToTask(dealId: string, taskIndex: number, resultDigest: string) {
251-
const taskId = getTaskId(dealId, taskIndex);
252-
const workerTaskStake = await iexecPoco
253-
.viewDeal(dealId)
254-
.then((deal) => deal.workerStake.toNumber());
255-
const { resultHash, resultSeal } = buildResultHashAndResultSeal(taskId, resultDigest, worker1);
256-
const schedulerSignature = await buildAndSignContributionAuthorizationMessage(
257-
worker1.address,
258-
taskId,
259-
AddressZero,
260-
scheduler,
261-
);
262-
await iexecWrapper.depositInIexecAccount(worker1, workerTaskStake);
263-
await iexecPoco
264-
.connect(worker1)
265-
.contribute(taskId, resultHash, resultSeal, AddressZero, '0x', schedulerSignature)
266-
.then((tx) => tx.wait());
267-
return taskId;
268-
}
269-
270239
async function verifyTaskStatusAndResult(taskId: string, expectedStatus: number) {
271240
const task = await iexecPoco.viewTask(taskId);
272241
expect(task.status).to.equal(expectedStatus);

0 commit comments

Comments
 (0)