Effect Network contracts V2
Summary
Effect Network V2 is an improved implementation of the network smart contracts. At its core is a new reservation and qualication system that is more performant and makes it easier for client integrations.
This version requires a new deployment of the force.efx contract. We will provide an automatic migration of all qualifications. Campaign data will be accessible as a backup but not be migrated to the new contract.
Features
The following main features will be enabled by this update:
Instant reservations The highlight of this update: the smart contract is now in charge of assigning a worker to a task. Previously, the logic for selecting a task to work on was embedded in the SDK. The SDK would communicate to the smart contract which task it wants to work on. This was the source of many errors and performance issues on the platform. It also puts a lot of complexity on the implementation of APIs.
In the new system, a client implementation just has to call reservetask on a campaign, and the smart contract will efficiently dispatch a suitable task to the worker. There is no chance for race conditions.
Infinite repetitions There is no longer a limit on the amount of repetitions a batch can have (this used to be a round 50). This enables high-repetition tasks like questionnaire and play testing, and enables us to use qualififiers that never expire.
Better campaign indexing The smart contracts have improved data and indices for fetching active campaigns. Clients no longer have to fetch all submission data to determine which tasks they can work on (because of automated reservations). This removes most loading times and puts less strain on our RPC nodes.
Task expiration per campaign Campaigns can now specify after how long reservations expire, this used to be global.
NFT qualifications Qualification have been swapped with AtomicAsset NFTs. Campaigns can filter on specific assets, collections, or templates. Additionally campaigns can filter on on-chain NFT attributes, which enables an extremely dynamic and portable qualification system.
Effect Network will provide a standard collection of NFTs, mirrored from the current qualification set, that embed expected qualification properties (like being soulbound and having a revokable attribute). These will be airdropped to the mirror the qualification table.
Task streaming* With the new reservation system, clients will be able to reserve tasks ahead in a campaign that is currently empty. They will be able to receive a push notification as soon the campaign receives more tasks and their reservation becomes active. This eliminates "task wars" (race conditions when users try to reserve much wanted tasks). It is also a requirement for allowing AI-agents on the platform.
Skip tasks* The new reservation system allows for workers to skip tasks they do not like, this is a much requested feature that was not possible in the previous system.
Implementation
This section explains how to implement a client for the new structure:
Tables
-
[new]
reservation: contains active reservations -
submission: contains results after user submitted task -
[new]
acctaskidx: track which task index a worker is at per campaign -
[new]
repsdone: track how many repetitions are completed for each task index in a campaign (only aftertasks_done) -
campaign,batch,payment: unchanged
Reservation flow for clients
Find campaigns to work on
- Get all AtomicAssets of the user
- Get all rows from the
campaignstable - Filter on active ones:
campaign.total_tasks>campaign.tasks_done
Resolve qualifications
- Check each entry in the
campaign.qualisvector. It has the following structure:
{"type": 0, "address": ["uint32", 123], "data_filter": null}
type 0 = AtomicAsset collection name (eosio::name)
type 1 = AtomicAsset template name (eosio::name)
type 2 = AtomicAsset asset ID (uint32)
address = a variant to filter on. specify as ["type", value] where type is "name" or "uint32" (see types above)
data_filter = filters for NFT attributes, can be left `null` for now
- Search through the users AtomicAssets and filter create a list of the Asset IDs (integers) that match the Quali. This array of Asset IDs must align with the qualification array
- Filter the campaign list on the ones that the user qualifies for
Find active reservations
- To find all users reservation: filter the
reservationtable by account_id (index = 3) - To find the user reservation in a campaign: filter on
acccamp(index 1) with composite index(uint64_t{account_id.value()} << 32) | campaign_id
Reserve a task To work on a task in a campaign:
- Fetch the last task index the user did from the
acctaskidxtable. This can be directly fetched using the composite primary key:(uint64_t{account_id} << 32) | campaign_id; - Call
reservetask(campaign_id, account_id, quali_assets, payer, sig)-
quali_assets: can benull, then the smart contract will search through all the assets of the user, which consumes more CPU -
sig(for BSC users only): to avoid replay attacks, the signature is composed of(mark)(last_task_done)(campaign_id). Themarkvalue is6
-
- Wait for the transaction to process, find the reserved task by polling as described in find active reservations
Fetch the task data
- Load the batch the task is in (get
_task_.batch_idfrom thebatchtable) - Get the batch IPFS hash from
batch.content.value - Load the IPFS object and confirm it is a JSON array. Get the
_task_.task_idxth item from the array - Render the campaign template with that task data
Submit task
- Call
submittask(camapign_id, task_idx, data, account_id, sig). Note to use_task_.task_idxfor thetask_idxparameter (not the ID).-
sig(for BSC only): to avoid replay attacks, the signature is(mark)(campaign_id)(task_idx)(data). Themarkvalue is5.
-
Reserve next task The same process as above, but make sure to update last_task_done for BSC users
Review Effect Network Contract v2
Some review points for the implementation details for Effect Network Smart Contract Spec
Instant Reservations
I think it's useful to be explicit about how this will speed up the frontend. The frontend won't need to do all the work of downloading data from the blockchain to do the checks.
Infinite Reps
Side note, What will be the new limit for how large a batch can be? Are we still maintaining the campaign, batch, task structure?
Better campaign indexing
The frontend comment mentioned in [Instant Reservations](#Instant Resevations ✅) could also apply here.
Task expiration per campaign
I can't remember if we ever had an issue with this, I would classify this as lower priority compared to the other features in this list and the other key elements I mention written down below.
NFT Qualis
This should help make a user profile more valuable and should help mitigate users who create throw away accounts.
Task Streaming
Could you expand a little bit on how this could help with allowing-AI agents?
Skip tasks
Agreed that this is a needed feature. Especially with larger datasets, where users try to scam the task, instead of skipping it when it gets too dificult.
Other notes
There are some key elements that, I think, are still missing:
Custom payout times
The current payout time is too short. Especially if we want to be able to validate tasks. We need a mechanism to adjust the payout time per batch
Price per batch instead of price per campaign
We have had issues before where we adjusted the price of a campaign, and it ended up affecting operations, Where users were annoyed with the payout because it did not conform to their expectations.
Task rejection as Requestor
We need a mechanism to actually reject a task and reclaim the tokens that are in escrow for the user. There is no mechanism currently to do this, and I think it will help the quality of the submissions if users know their funds are reliant on high-quality submissions.
I think it's useful to be explicit about how this will speed up the frontend.
Depends on the SDK / frontend implementation. As finding possible reservations was extremely slow, I'm satisfied with the observation that this problem is now eliminated.
Side note, What will be the new limit for how large a batch can be? Are we still maintaining the campaign, batch, task structure?
Good point. Technically there is no upper-limit anymore, but we probably want to set one as batch-removal is the only way to clear RAM for users or relayers. It is also possible to go with a time-based limit
[task expiration] ... I would classify this as lower priority compared to the other features in this list and the other key elements
It is already part of the implementation in the PR
Task Streaming, Could you expand a little bit on how this could help with allowing-AI agents?
AI-agents reverse the platform from a task-first queue to a worker-first queue. In the new system we now longer have "task-wars" where multiple participants (users or AI) are trying to claim the same task. The proposed method is to allow making reservations in advance, before tasks are even created yet. This needs a full write-up, but hope that you get the gist of it
Custom [per batch] payout times
This should not be hard to implement, I see if it can be included in this PR. This would be a payout time per campaign, not batch (see my comment below). Out of interest, could you elaborate a bit on why they are too low now?
Price per batch instead of price per campaign
In the new model, batches are abstracted away (user can not decide in which batch they will work). So we are trying to keep batches more uniform; they are primarily meant to append data to an existing campaign. If you want custom payout times, task expiration, or prices, you will have to create more campaigns.
BTW, in V1 price per batch is already a smart contract feature, as in, if you change the campaign price, existing batches are not affected. The annoyance you mention is an shortcoming in the frontend
Task rejection as Requestor
I agree that the validation system is important, I will try to include it in the V2 architecture