Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Changelog

## vNEXT

- Remove `smock` from unit tests:
- IexecPocoDelegate (#149)
- IexecPocoBoost (#148)
- Migrate unit test files to Typescript & Hardhat:
- ERC1154 (#145, #146, #147)
Expand Down
12 changes: 0 additions & 12 deletions contracts/tools/testing/IexecPocoCompositeDelegate.sol

This file was deleted.

221 changes: 135 additions & 86 deletions test/byContract/IexecAccessors/IexecAccessors.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH <contact@iex.ec>
// SPDX-License-Identifier: Apache-2.0

import { AddressZero } from '@ethersproject/constants';
import { AddressZero, HashZero } from '@ethersproject/constants';
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { deployments, ethers, expect } from 'hardhat';
Expand All @@ -26,11 +26,19 @@ import { IexecWrapper } from '../../utils/IexecWrapper';
/**
* Test state view functions.
*/
describe('IexecAccessors', async () => {
let proxyAddress: string;
let iexecPocoAsAnyone: IexecInterfaceNative;
let anyone: SignerWithAddress;

const { results, resultDigest } = buildUtf8ResultAndDigest('result');
const { resultsCallback, callbackResultDigest } = buildResultCallbackAndDigest(123);

let proxyAddress: string;
let iexecPocoAsAnyone: IexecInterfaceNative;
let iexecWrapper: IexecWrapper;
let [appAddress, datasetAddress, workerpoolAddress]: string[] = [];
let [requester, scheduler, worker1, anyone]: SignerWithAddress[] = [];
let ordersAssets: OrdersAssets;
let callbackAddress: string;

describe('IexecAccessors', async () => {
beforeEach('Deploy', async () => {
// Deploy all contracts
proxyAddress = await loadHardhatFixtureDeployment();
Expand All @@ -40,120 +48,148 @@ describe('IexecAccessors', async () => {

async function initFixture() {
const accounts = await getIexecAccounts();
({ anyone } = accounts);
({ requester, scheduler, worker1, anyone } = accounts);
iexecWrapper = new IexecWrapper(proxyAddress, accounts);
({ appAddress, datasetAddress, workerpoolAddress } = await iexecWrapper.createAssets());
iexecPocoAsAnyone = IexecInterfaceNative__factory.connect(proxyAddress, anyone);
ordersAssets = {
app: appAddress,
dataset: datasetAddress,
workerpool: workerpoolAddress,
};
callbackAddress = await new TestClient__factory()
.connect(anyone)
.deploy()
.then((contract) => contract.deployed())
.then((contract) => contract.address);
}

it('name', async function () {
expect(await iexecPocoAsAnyone.name()).to.equal('Staked RLC');
});

it('symbol', async function () {
expect(await iexecPocoAsAnyone.symbol()).to.equal('SRLC');
});

it('decimals', async function () {
expect(await iexecPocoAsAnyone.decimals()).to.equal(9n);
});

it('totalSupply', async function () {
expect(await iexecPocoAsAnyone.totalSupply()).to.equal(0n);
});

// TODO test the case where token() == 0x0 in native mode.
it('token', async function () {
expect(await iexecPocoAsAnyone.token()).to.equal(
'0x5FbDB2315678afecb367f032d93F642f64180aa3',
);
});

it('viewTask', async function () {
const { dealId, taskId, taskIndex, startTime, timeRef } = await createDeal();
await initializeTask(dealId, taskIndex);

const contributionDeadlineRatio = (
await iexecPocoAsAnyone.contribution_deadline_ratio()
).toNumber();
const finalDeadlineRatio = (await iexecPocoAsAnyone.final_deadline_ratio()).toNumber();

const task = await iexecPocoAsAnyone.viewTask(taskId);
expect(task.status).to.equal(TaskStatusEnum.ACTIVE);
expect(task.dealid).to.equal(dealId);
expect(task.idx).to.equal(taskIndex);
expect(task.timeref).to.equal(timeRef);
expect(task.contributionDeadline).to.equal(startTime + timeRef * contributionDeadlineRatio);
expect(task.revealDeadline).to.equal(0);
expect(task.finalDeadline).to.equal(startTime + timeRef * finalDeadlineRatio);
expect(task.consensusValue).to.equal(HashZero);
expect(task.revealCounter).to.equal(0);
expect(task.winnerCounter).to.equal(0);
expect(task.contributors.length).to.equal(0);
expect(task.resultDigest).to.equal(HashZero);
expect(task.results).to.equal('0x');
expect(task.resultsTimestamp).to.equal(0);
expect(task.resultsCallback).to.equal('0x');
});

it('countCategory', async function () {
expect(await iexecPocoAsAnyone.countCategory()).to.equal(5);
});

it('appRegistry', async function () {
expect(await iexecPocoAsAnyone.appregistry()).to.equal(
(await deployments.get('AppRegistry')).address,
);
});

it('datasetRegistry', async function () {
expect(await iexecPocoAsAnyone.datasetregistry()).to.equal(
(await deployments.get('DatasetRegistry')).address,
);
});

it('workerpoolRegistry', async function () {
expect(await iexecPocoAsAnyone.workerpoolregistry()).to.equal(
(await deployments.get('WorkerpoolRegistry')).address,
);
});

it('teeBroker', async function () {
expect(await iexecPocoAsAnyone.teebroker()).to.equal(ethers.constants.AddressZero);
});

it('callbackGas', async function () {
expect(await iexecPocoAsAnyone.callbackgas()).to.equal(100_000n);
});

it('contributionDeadlineRatio', async function () {
expect(await iexecPocoAsAnyone.contribution_deadline_ratio()).to.equal(7);
});

it('revealDeadlineRatio', async function () {
expect(await iexecPocoAsAnyone.reveal_deadline_ratio()).to.equal(2n);
});

it('finalDeadlineRatio', async function () {
expect(await iexecPocoAsAnyone.final_deadline_ratio()).to.equal(10n);
});

it('workerpoolStakeRatio', async function () {
expect(await iexecPocoAsAnyone.workerpool_stake_ratio()).to.equal(30n);
});

it('kittyRatio', async function () {
expect(await iexecPocoAsAnyone.kitty_ratio()).to.equal(10n);
});

it('kittyMin', async function () {
expect(await iexecPocoAsAnyone.kitty_min()).to.equal(1_000_000_000n);
});

it('kittyAddress', async function () {
expect(await iexecPocoAsAnyone.kitty_address()).to.equal(
'0x99c2268479b93fDe36232351229815DF80837e23',
);
});

it('groupMemberPurpose', async function () {
expect(await iexecPocoAsAnyone.groupmember_purpose()).to.equal(4n);
});

it('eip712domainSeparator', async function () {
expect(await iexecPocoAsAnyone.eip712domain_separator()).to.equal(
'0xfc2178d8b8300e657cb9f8b5a4d1957174cf1392e294f3575b82a9cea1da1c4b',
);
});

describe('resultFor', () => {
let iexecWrapper: IexecWrapper;
let [appAddress, datasetAddress, workerpoolAddress]: string[] = [];
let [requester, scheduler, worker1]: SignerWithAddress[] = [];
let ordersAssets: OrdersAssets;
const { results, resultDigest } = buildUtf8ResultAndDigest('result');
const { resultsCallback, callbackResultDigest } = buildResultCallbackAndDigest(123);

beforeEach(async () => {
const accounts = await getIexecAccounts();
iexecWrapper = new IexecWrapper(proxyAddress, accounts);
({ requester, scheduler, worker1 } = accounts);
({ appAddress, datasetAddress, workerpoolAddress } = await iexecWrapper.createAssets());
ordersAssets = {
app: appAddress,
dataset: datasetAddress,
workerpool: workerpoolAddress,
};
});

it('Should get result of task', async function () {
const oracleConsumerInstance = await new TestClient__factory()
.connect(anyone)
.deploy()
.then((contract) => contract.deployed());
const orders = buildOrders({
assets: ordersAssets,
requester: requester.address,
callback: oracleConsumerInstance.address,
});
const { dealId, taskId, taskIndex } = await iexecWrapper.signAndMatchOrders(
...orders.toArray(),
);
const { dealId, taskId, taskIndex } = await createDeal();

await initializeTask(dealId, taskIndex).then(() =>
contributeTask(dealId, taskIndex, callbackResultDigest),
contributeToTask(dealId, taskIndex, callbackResultDigest),
);
await iexecPocoAsAnyone
.connect(worker1)
Expand All @@ -164,66 +200,79 @@ describe('IexecAccessors', async () => {
.finalize(taskId, results, resultsCallback)
.then((tx) => tx.wait());
const task = await iexecPocoAsAnyone.viewTask(taskId);
await expect(task.status).to.equal(TaskStatusEnum.COMPLETED);
await expect(await iexecPocoAsAnyone.callStatic.resultFor(taskId)).to.equal(
resultsCallback,
);
expect(task.status).to.equal(TaskStatusEnum.COMPLETED);
expect(await iexecPocoAsAnyone.callStatic.resultFor(taskId)).to.equal(resultsCallback);
});
it('Should not get result when task is not completed', async function () {
const volume = 3;
const orders = buildOrders({
assets: ordersAssets,
requester: requester.address,
volume,
});

const { dealId } = await iexecWrapper.signAndMatchOrders(...orders.toArray());
it('Should not get result when task is not completed', async function () {
const { dealId } = await createDeal(3);

const unsetTaskId = getTaskId(dealId, 0);
const activeTaskId = await initializeTask(dealId, 1);
const revealingTaskId = await initializeTask(dealId, 2).then(() =>
contributeTask(dealId, 2, resultDigest),
contributeToTask(dealId, 2, resultDigest),
);

await verifyTaskStatusAndResult(unsetTaskId, TaskStatusEnum.UNSET);
await verifyTaskStatusAndResult(activeTaskId, TaskStatusEnum.ACTIVE);
await verifyTaskStatusAndResult(revealingTaskId, TaskStatusEnum.REVEALING);
});
});
});

// Helper function to initialize and contribute to a task
const initializeTask = async (dealId: string, taskIndex: number) => {
await iexecPocoAsAnyone.initialize(dealId, taskIndex).then((tx) => tx.wait());
return getTaskId(dealId, taskIndex);
};
/**
* Helper function to create a deal with a specific volume.
*/
async function createDeal(volume: number = 1) {
const orders = buildOrders({
assets: ordersAssets,
requester: requester.address,
volume,
callback: callbackAddress,
});
const { dealId, taskId, taskIndex, startTime } = await iexecWrapper.signAndMatchOrders(
...orders.toArray(),
);
const dealCategory = (await iexecPocoAsAnyone.viewDeal(dealId)).category;
const timeRef = (
await iexecPocoAsAnyone.viewCategory(dealCategory)
).workClockTimeRef.toNumber();
return { dealId, taskId, taskIndex, startTime, timeRef };
}

const contributeTask = async (dealId: string, taskIndex: number, resultDigest: string) => {
const taskId = getTaskId(dealId, taskIndex);
const workerTaskStake = await iexecPocoAsAnyone
.viewDeal(dealId)
.then((deal) => deal.workerStake.toNumber());
const { resultHash, resultSeal } = buildResultHashAndResultSeal(
taskId,
resultDigest,
worker1,
);
const schedulerSignature = await buildAndSignContributionAuthorizationMessage(
worker1.address,
taskId,
AddressZero,
scheduler,
);
await iexecWrapper.depositInIexecAccount(worker1, workerTaskStake);
await iexecPocoAsAnyone
.connect(worker1)
.contribute(taskId, resultHash, resultSeal, AddressZero, '0x', schedulerSignature)
.then((tx) => tx.wait());
return taskId;
};
/**
* Helper function to initialize a task.
*/
async function initializeTask(dealId: string, taskIndex: number) {
await iexecPocoAsAnyone.initialize(dealId, taskIndex).then((tx) => tx.wait());
return getTaskId(dealId, taskIndex);
}

const verifyTaskStatusAndResult = async (taskId: string, expectedStatus: number) => {
const task = await iexecPocoAsAnyone.viewTask(taskId);
await expect(task.status).to.equal(expectedStatus);
await expect(iexecPocoAsAnyone.resultFor(taskId)).to.be.revertedWith('task-pending');
};
});
});
/**
* Helper function to contribute to a task.
*/
async function contributeToTask(dealId: string, taskIndex: number, resultDigest: string) {
const taskId = getTaskId(dealId, taskIndex);
const workerTaskStake = await iexecPocoAsAnyone
.viewDeal(dealId)
.then((deal) => deal.workerStake.toNumber());
const { resultHash, resultSeal } = buildResultHashAndResultSeal(taskId, resultDigest, worker1);
const schedulerSignature = await buildAndSignContributionAuthorizationMessage(
worker1.address,
taskId,
AddressZero,
scheduler,
);
await iexecWrapper.depositInIexecAccount(worker1, workerTaskStake);
await iexecPocoAsAnyone
.connect(worker1)
.contribute(taskId, resultHash, resultSeal, AddressZero, '0x', schedulerSignature)
.then((tx) => tx.wait());
return taskId;
}

const verifyTaskStatusAndResult = async (taskId: string, expectedStatus: number) => {
const task = await iexecPocoAsAnyone.viewTask(taskId);
expect(task.status).to.equal(expectedStatus);
await expect(iexecPocoAsAnyone.resultFor(taskId)).to.be.revertedWith('task-pending');
};
Loading