Skip to content

Commit 27dfcd1

Browse files
authored
Merge pull request #14 from singnet/job
Refactor Job contract logic
2 parents 6b63f72 + ff0a4d8 commit 27dfcd1

20 files changed

+351
-604
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ or
2828

2929
```bash
3030
truffle test
31-
```
31+
```
32+
33+
## Flattening
34+
35+
`solidity_flattener contracts/Contract.sol --solc-paths=zeppelin-solidity=$(pwd)/node_modules/zeppelin-solidity/ --output contract.sol`
36+

contracts/agent/Agent.sol

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import "zeppelin-solidity/contracts/ownership/Ownable.sol";
66
contract Agent is AgentInterface, Ownable {
77

88
bytes[] public packets;
9-
MarketJobInterface public job;
109

1110
function sendPacket(address target, bytes packet) external onlyOwner {
1211
Agent(target).appendPacket(packet);
@@ -21,8 +20,4 @@ contract Agent is AgentInterface, Ownable {
2120
return packets[id];
2221
}
2322

24-
function setJob(MarketJob _job) external returns (address) {
25-
job = _job;
26-
}
27-
2823
}

contracts/agent/AgentInterface.sol

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
pragma solidity ^0.4.18;
22

3-
import "../market/MarketJob.sol";
43

54
contract AgentInterface {
65

76
function sendPacket(address target, bytes packet) external;
87
function appendPacket(bytes packet) external;
98
function getPacket(uint id) external constant returns (bytes);
10-
function setJob(MarketJob _job) external returns (address);
119

1210
}

contracts/market/Escrow.sol

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,98 @@
1-
pragma solidity ^0.4.11;
1+
pragma solidity ^0.4.18;
22

3-
import "zeppelin-solidity/contracts/ownership/Ownable.sol";
3+
import "./Job.sol";
4+
import "zeppelin-solidity/contracts/token/ERC20.sol";
45

5-
contract Escrow is Ownable {
66

7+
contract Escrow is Job {
8+
/**
9+
* @dev Kovan token.
10+
* https://kovan.etherscan.io/token/0x3b226ff6aad7851d3263e53cb7688d13a07f6e81#readContract
11+
*/
12+
ERC20 public token;
713

8-
address public beneficiary;
14+
/**
15+
* @dev Fund Timelock in milliseconds
16+
*/
17+
uint256 public timelock;
18+
19+
/**
20+
* @dev Deposited event
21+
*/
22+
event Deposited(address payer, uint256 amount);
923

10-
event Deposited(address indexed from, uint amount);
24+
/**
25+
* @dev Deposited event
26+
*/
27+
event Withdrew(address payee, uint256 amount);
1128

12-
function Escrow(address _beneficiary) {
13-
beneficiary = _beneficiary;
29+
/**
30+
* @dev Escrow constructor.
31+
* @param _payer An agent who pays the job.
32+
* @param _payee An agent to whom the job is paid.
33+
* @param _timelock how many seconds after end should be the window for rejections
34+
* @param _validator who should check if rejected
35+
* @param _reward reward for validator
36+
*/
37+
function Escrow(
38+
address _token,
39+
address _payer,
40+
address _payee,
41+
uint256 _timelock,
42+
address _validator,
43+
uint256 _reward ) public
44+
{
45+
token = ERC20(_token);
46+
payer = _payer;
47+
payee = _payee;
48+
49+
timelock = _timelock;
50+
//Reward for the validator in case of dispute
51+
validator = _validator;
52+
reward = _reward;
53+
54+
//Who actually should deliver the job, capable of setResult and close the job
55+
//Beaware that who can withdraw money is still the payee, not the provider
56+
provider = payee;
57+
58+
}
59+
60+
/**
61+
* @dev Deposit function.
62+
* @param _amount Token amount to fill the price
63+
* @param _descriptor bytes hash that represent the input for the job
64+
*/
65+
function deposit(uint256 _amount, bytes32 _descriptor) public {
66+
require(msg.sender == payer);
67+
require(token.transferFrom(msg.sender, this, _amount));
68+
Deposited(msg.sender, _amount);
69+
70+
descriptor = _descriptor;
71+
price = _amount;
72+
start = now;
73+
74+
Started(payer, payee, descriptor, address(this));
1475
}
1576

16-
function () payable {
17-
if (msg.value <= 0) {
18-
return;
19-
}
77+
/**
78+
* @dev withdraw all funds from escrow
79+
*/
80+
function withdraw() public {
81+
require(msg.sender == payee);
82+
require(timelockExpired());
83+
require(!isRejected);
2084

21-
Deposited(msg.sender, msg.value);
85+
uint256 balance = token.balanceOf(this);
86+
require (balance > 0);
87+
88+
require(token.transfer(msg.sender, balance));
89+
Withdrew(msg.sender, balance);
2290
}
2391

24-
function releaseFunds() onlyOwner {
25-
beneficiary.transfer(this.balance);
92+
function timelockExpired() internal constant returns(bool) {
93+
bool isExpired = (end + timelock) <= block.timestamp;
94+
return isCompleted && isExpired ;
2695
}
27-
}
96+
97+
98+
}

contracts/market/Job.sol

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,61 @@
11
pragma solidity ^0.4.18;
22

3-
contract Job {
4-
uint256 public status = 0;
5-
bytes32 public jobDescriptor;
6-
bytes32 public jobResult;
3+
import "./JobValidator.sol";
4+
/**
5+
* @title The wrapped Job contract
6+
*/
7+
contract Job is JobValidator {
8+
9+
/**
10+
* @dev Determines if job is completed
11+
*/
12+
bool public isCompleted = false;
13+
14+
/**
15+
* @dev Who can set the result
16+
*/
17+
address public provider;
18+
19+
/**
20+
* @dev Price in AGI for the exection of the job
21+
* (10**8 cogs === 1 AGI)
22+
*/
23+
uint256 public price;
24+
25+
/**
26+
* @dev Started event
27+
*/
28+
event Started(address indexed payer, address indexed payee, bytes32 descriptor, address job);
29+
30+
/**
31+
* @dev Set result of this Job
32+
* @param _result Result data hash
33+
*/
34+
function setResult(bytes32 _result) public returns (bool) {
35+
require(msg.sender == provider);
36+
require(descriptor.length > 0);
737

8-
uint256 public start;
9-
uint256 public end;
10-
11-
address public payer;
12-
address public payee;
13-
14-
event JobStarted(address indexed payer, address indexed payee, bytes32 jobDescriptor, address jobAddress);
15-
event JobCompleted(bytes32 jobResult, address jobAddress);
38+
end = now;
39+
40+
Result(_result);
41+
result = _result;
1642

17-
function setJobStarted(address _payer, address _payee, bytes32 _jobDescriptor) public {
18-
require(status < 1);
19-
payer = _payer;
20-
payee = _payee;
21-
jobDescriptor = _jobDescriptor;
22-
status = 1;
23-
start = now;
43+
Completed();
44+
isCompleted = true;
2445

25-
JobStarted(payer, payee, jobDescriptor, address(this));
46+
return true;
2647
}
2748

28-
function setJobCompleted(bytes32 _jobResult) public {
29-
require(msg.sender == payee);
30-
require(status < 2);
31-
status = 2;
32-
jobResult = _jobResult;
33-
end = now;
49+
/**
50+
* @dev The payee can change the provider address
51+
* @param _provider New provider
52+
*/
53+
function setProvider(address _provider) public returns(bool) {
54+
require(msg.sender == payee);
55+
provider = _provider;
56+
return true;
57+
}
3458

35-
JobCompleted(jobResult, address(this));
3659

37-
}
3860

3961
}

contracts/market/JobStandard.sol

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
pragma solidity ^0.4.18;
2+
3+
/**
4+
* @title The Job Interface contract
5+
*/
6+
7+
contract JobStandard {
8+
/**
9+
* @dev Starting hash of the job
10+
*/
11+
bytes32 public descriptor;
12+
13+
/**
14+
* @dev Result hash of the job
15+
*/
16+
bytes32 public result;
17+
18+
/**
19+
* @dev Start time timestamp
20+
*/
21+
uint256 public start;
22+
23+
/**
24+
* @dev End time timestamp
25+
*/
26+
uint256 public end;
27+
28+
/**
29+
* @dev An agent who pays the job.
30+
*/
31+
address public payer;
32+
33+
/**
34+
* @dev An agent to whom the job is paid.
35+
*/
36+
address public payee;
37+
38+
/**
39+
* @dev Broadcast new hash as job result.
40+
*/
41+
event Result(bytes32 result);
42+
}

contracts/market/JobValidator.sol

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
pragma solidity ^0.4.18;
2+
3+
import "./JobStandard.sol";
4+
5+
/**
6+
* @title The Job Validator contract
7+
*/
8+
9+
contract JobValidator is JobStandard {
10+
11+
/**
12+
* @dev Reward for validator in AGI.
13+
*/
14+
address public validator;
15+
16+
/**
17+
* @dev rejection status
18+
*/
19+
bool public isRejected = false;
20+
21+
/**
22+
* @dev Reward for validator in AGI.
23+
*/
24+
uint256 public reward;
25+
26+
/**
27+
* @dev Completed event to notice the validators pool
28+
*/
29+
event Completed();
30+
31+
/**
32+
* @dev Approved event to notice the parties
33+
*/
34+
event Accepted();
35+
36+
/**
37+
* @dev Rejected event to notice the parties
38+
*/
39+
event Rejected();
40+
41+
42+
/**
43+
* @dev Confirm job result
44+
* Is optional, even if not called by the payer at the expiration time
45+
* funds will be available for to payee
46+
*/
47+
function accept() public {
48+
require(msg.sender == payer);
49+
Accepted();
50+
}
51+
52+
/**
53+
* @dev Reject job result
54+
*/
55+
function reject() public {
56+
require(msg.sender == payer);
57+
isRejected = true;
58+
Rejected();
59+
}
60+
61+
}

0 commit comments

Comments
 (0)