Skip to content

Commit

Permalink
Feat: Add JobRequesterId to createEscrow function (#853)
Browse files Browse the repository at this point in the history
* add job requester id to escrow factory create function

* update contract Readme

* fix sdk

* fix fortune test

* update readme
  • Loading branch information
leric7 authored Aug 31, 2023
1 parent 8e27a4b commit 216c18e
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 64 deletions.
4 changes: 2 additions & 2 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ On the other hand, it can be cancelled anytime.

EscrowFactory allows job launchers to create new Escrow contracts.

- `createEscrow(token, trustedHandlers)`
- `createEscrow(token, trustedHandlers, jobRequesterId)`

Create a new escrow, which uses ERC20 token for payment, as well as extra trusted handlers. Job launcher is canceler itself, and the job duration is 100 days.
Create a new escrow, which uses ERC20 token for payment, as well as extra trusted handlers. Job launcher is canceler itself, and the job duration is 100 days. Job Requester Id is passed to keep track of job creators. Here, jobRequesterId is an internal id of the Job Launcher, and it can be used to identify the jobs requested by each Job Requester without crossing data between Subgraph and database.

- `hasEscrow(escrow)`

Expand Down
6 changes: 4 additions & 2 deletions packages/core/contracts/EscrowFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
address public staking;

event Launched(address token, address escrow);
event LaunchedV2(address token, address escrow, string jobRequesterId);

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
Expand All @@ -39,7 +40,8 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {

function createEscrow(
address token,
address[] memory trustedHandlers
address[] memory trustedHandlers,
string memory jobRequesterId
) public returns (address) {
bool hasAvailableStake = IStaking(staking).hasAvailableStake(
msg.sender
Expand All @@ -59,7 +61,7 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
counter++;
escrowCounters[address(escrow)] = counter;
lastEscrow = address(escrow);
emit Launched(token, lastEscrow);
emit LaunchedV2(token, lastEscrow, jobRequesterId);
return lastEscrow;
}

Expand Down
6 changes: 4 additions & 2 deletions packages/core/contracts/test/EscrowFactoryV0.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable {
address public staking;

event Launched(address token, address escrow);
event LaunchedV2(address token, address escrow, string jobRequesterId);

function initialize(address _staking) external payable virtual initializer {
__Ownable_init_unchained();
Expand All @@ -34,7 +35,8 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable {

function createEscrow(
address token,
address[] memory trustedHandlers
address[] memory trustedHandlers,
string memory jobRequesterId
) public returns (address) {
bool hasAvailableStake = IStaking(staking).hasAvailableStake(
msg.sender
Expand All @@ -54,7 +56,7 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable {
counter++;
escrowCounters[address(escrow)] = counter;
lastEscrow = address(escrow);
emit Launched(token, lastEscrow);
emit LaunchedV2(token, lastEscrow, jobRequesterId);
return lastEscrow;
}

Expand Down
23 changes: 16 additions & 7 deletions packages/core/test/EscrowFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('EscrowFactory', function () {

let token: HMToken, escrowFactory: EscrowFactory, staking: Staking;

const jobRequesterId = 'job-requester-id';
const minimumStake = 2;
const lockPeriod = 2;

Expand All @@ -22,10 +23,10 @@ describe('EscrowFactory', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, trustedHandlers)
.createEscrow(token.address, trustedHandlers, jobRequesterId)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

return event;
Expand Down Expand Up @@ -96,7 +97,11 @@ describe('EscrowFactory', function () {
await expect(
escrowFactory
.connect(operator)
.createEscrow(token.address, [await reputationOracle.getAddress()])
.createEscrow(
token.address,
[await reputationOracle.getAddress()],
jobRequesterId
)
).to.be.revertedWith('Needs to stake HMT tokens to create an escrow.');
});

Expand All @@ -113,10 +118,10 @@ describe('EscrowFactory', function () {
await expect(
escrowFactory
.connect(operator)
.createEscrow(token.address, trustedHandlers)
.createEscrow(token.address, trustedHandlers, jobRequesterId)
)
.to.emit(escrowFactory, 'Launched')
.withArgs(token.address, anyValue);
.to.emit(escrowFactory, 'LaunchedV2')
.withArgs(token.address, anyValue, jobRequesterId);
});

it('Should find the newly created escrow from deployed escrow', async () => {
Expand Down Expand Up @@ -152,7 +157,11 @@ describe('EscrowFactory', function () {
await expect(
escrowFactory
.connect(operator)
.createEscrow(token.address, [await reputationOracle.getAddress()])
.createEscrow(
token.address,
[await reputationOracle.getAddress()],
jobRequesterId
)
).to.be.revertedWith('Needs to stake HMT tokens to create an escrow.');
});

Expand Down
17 changes: 13 additions & 4 deletions packages/core/test/RewardPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('RewardPool', function () {
const minimumStake = 2;
const lockPeriod = 2;
const rewardFee = 2;
const jobRequesterId = 'job-requester-id';

this.beforeAll(async () => {
[
Expand Down Expand Up @@ -136,10 +137,14 @@ describe('RewardPool', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [await validator.getAddress()])
.createEscrow(
token.address,
[await validator.getAddress()],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(token.address, 'token address is correct');
Expand Down Expand Up @@ -226,10 +231,14 @@ describe('RewardPool', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [await validator.getAddress()])
.createEscrow(
token.address,
[await validator.getAddress()],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(token.address, 'token address is correct');
Expand Down
57 changes: 41 additions & 16 deletions packages/core/test/Staking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('Staking', function () {
const minimumStake = 2;
const lockPeriod = 2;
const rewardFee = 1;
const jobRequesterId = 'job-requester-id';

let owner: Signer,
validator: Signer,
Expand Down Expand Up @@ -252,10 +253,14 @@ describe('Staking', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [await validator.getAddress()])
.createEscrow(
token.address,
[await validator.getAddress()],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(token.address, 'token address is correct');
Expand Down Expand Up @@ -350,10 +355,14 @@ describe('Staking', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [await validator.getAddress()])
.createEscrow(
token.address,
[await validator.getAddress()],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(token.address, 'token address is correct');
Expand Down Expand Up @@ -542,10 +551,14 @@ describe('Staking', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [await validator.getAddress()])
.createEscrow(
token.address,
[await validator.getAddress()],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(
Expand Down Expand Up @@ -608,10 +621,14 @@ describe('Staking', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [await validator.getAddress()])
.createEscrow(
token.address,
[await validator.getAddress()],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(
Expand Down Expand Up @@ -667,10 +684,14 @@ describe('Staking', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [await validator.getAddress()])
.createEscrow(
token.address,
[await validator.getAddress()],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(token.address, 'token address is correct');
Expand Down Expand Up @@ -857,14 +878,18 @@ describe('Staking', function () {
const result = await (
await escrowFactory
.connect(operator)
.createEscrow(token.address, [
await validator.getAddress(),
await reputationOracle.getAddress(),
await recordingOracle.getAddress(),
])
.createEscrow(
token.address,
[
await validator.getAddress(),
await reputationOracle.getAddress(),
await recordingOracle.getAddress(),
],
jobRequesterId
)
).wait();
const event = result.events?.find(({ topics }) =>
topics.includes(ethers.utils.id('Launched(address,address)'))
topics.includes(ethers.utils.id('LaunchedV2(address,address,string)'))
)?.args;

expect(event?.token).to.equal(token.address, 'token address is correct');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ class Escrow {
factoryAddress
);
const gas = await escrowFactory.methods
.createEscrow(token, [])
.createEscrow(token, [], jobRequester)
.estimateGas({ from: jobRequester });
const gasPrice = await web3.eth.getGasPrice();
const result = await escrowFactory.methods
.createEscrow(token, [])
.createEscrow(token, [], jobRequester)
.send({ from: jobRequester, gas, gasPrice });
return result.events.Launched.returnValues.escrow;
return result.events.LaunchedV2.returnValues.escrow;
}

async fundEscrow(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ describe('Fortune', () => {

beforeEach(async () => {
await escrowFactory.methods
.createEscrow(token.options.address, [launcher.address])
.createEscrow(token.options.address, [launcher.address], 'job-requester')
.send({ from: launcher.address });

escrowAddress = await escrowFactory.methods.lastEscrow().call();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,16 @@ def __init__(self, web3: Web3):
address=self.network["factory_address"], abi=factory_interface["abi"]
)

def create_escrow(self, token_address: str, trusted_handlers: List[str]) -> str:
def create_escrow(
self, token_address: str, trusted_handlers: List[str], job_requester_id: str
) -> str:
"""
Creates an escrow contract that uses the token passed to pay oracle fees and reward workers.
Args:
tokenAddress (str): The address of the token to use for payouts
trusted_handlers (List[str]): Array of addresses that can perform actions on the contract
job_requester_id (str): The id of the job requester
Returns:
str: The address of the escrow created
Expand All @@ -192,13 +195,13 @@ def create_escrow(self, token_address: str, trusted_handlers: List[str]) -> str:
self.w3,
"Create Escrow",
self.factory_contract.functions.createEscrow(
token_address, trusted_handlers
token_address, trusted_handlers, job_requester_id
),
EscrowClientError,
)
return next(
(
self.factory_contract.events.Launched().process_log(log)
self.factory_contract.events.LaunchedV2().process_log(log)
for log in transaction_receipt["logs"]
if log["address"] == self.network["factory_address"]
),
Expand Down Expand Up @@ -241,6 +244,7 @@ def create_and_setup_escrow(
self,
token_address: str,
trusted_handlers: List[str],
job_requester_id: str,
escrow_config: EscrowConfig,
) -> str:
"""
Expand All @@ -249,6 +253,7 @@ def create_and_setup_escrow(
Args:
token_address (str): Token to use for pay outs
trusted_handlers (List[str]): Array of addresses that can perform actions on the contract
job_requester_id (str): The id of the job requester
escrow_config (EscrowConfig): Object containing all the necessary information to setup an escrow
Returns:
Expand All @@ -258,7 +263,9 @@ def create_and_setup_escrow(
EscrowClientError: If an error occurs while checking the parameters
"""

escrow_address = self.create_escrow(token_address, trusted_handlers)
escrow_address = self.create_escrow(
token_address, trusted_handlers, job_requester_id
)
self.setup(escrow_address, escrow_config)

return escrow_address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@ def create_escrow(self):
tx_hash = self.staking_client.factory_contract.functions.createEscrow(
self.staking_client.hmtoken_contract.address,
[self.gas_payer.address],
"job-requester",
).transact()

tx_receipt = self.staking_client.w3.eth.wait_for_transaction_receipt(tx_hash)

events = self.staking_client.factory_contract.events.Launched().process_receipt(
tx_receipt
events = (
self.staking_client.factory_contract.events.LaunchedV2().process_receipt(
tx_receipt
)
)
self.escrow_address = events[0].get("args", {}).get("escrow", "")

Expand Down
Loading

1 comment on commit 216c18e

@vercel
Copy link

@vercel vercel bot commented on 216c18e Aug 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

job-launcher-server – ./packages/apps/job-launcher/server

job-launcher-server-humanprotocol.vercel.app
job-launcher-server-git-develop-humanprotocol.vercel.app
job-launcher-server-nine.vercel.app

Please sign in to comment.