Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -791,11 +791,8 @@ describe('JobService', () => {
jobEntity.userId.toString(),
expect.objectContaining({
recordingOracle: jobEntity.recordingOracle,
recordingOracleFee: 1n,
reputationOracle: jobEntity.reputationOracle,
reputationOracleFee: 1n,
exchangeOracle: jobEntity.exchangeOracle,
exchangeOracleFee: 1n,
manifest: jobEntity.manifestUrl,
manifestHash: jobEntity.manifestHash,
}),
Expand Down
12 changes: 0 additions & 12 deletions packages/apps/job-launcher/server/src/modules/job/job.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,20 +317,8 @@ export class JobService {

const escrowConfig = {
recordingOracle: jobEntity.recordingOracle,
recordingOracleFee: await this.getOracleFee(
jobEntity.recordingOracle,
jobEntity.chainId,
),
reputationOracle: jobEntity.reputationOracle,
reputationOracleFee: await this.getOracleFee(
jobEntity.reputationOracle,
jobEntity.chainId,
),
exchangeOracle: jobEntity.exchangeOracle,
exchangeOracleFee: await this.getOracleFee(
jobEntity.exchangeOracle,
jobEntity.chainId,
),
manifest: jobEntity.manifestUrl,
manifestHash: jobEntity.manifestHash,
};
Expand Down
84 changes: 62 additions & 22 deletions packages/core/contracts/Escrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ import '@openzeppelin/contracts/utils/ReentrancyGuard.sol';

import './interfaces/IEscrow.sol';

interface IKVStore {
function get(
address _account,
string memory _key
) external view returns (string memory);
}

struct Fees {
uint256 reputation;
uint256 recording;
Expand All @@ -23,6 +30,8 @@ contract Escrow is IEscrow, ReentrancyGuard {
using SafeERC20 for IERC20;

string private constant ERROR_ZERO_ADDRESS = 'Zero address';
string private constant FEE_KEY = 'fee';
uint8 private constant MAX_ORACLE_FEE = 25;
uint32 private constant BULK_MAX_COUNT = 100;

event IntermediateStorage(string url, string hash);
Expand All @@ -34,6 +43,16 @@ contract Escrow is IEscrow, ReentrancyGuard {
address recordingOracle,
address exchangeOracle
);
event PendingV3(
string manifest,
string hash,
address reputationOracle,
address recordingOracle,
address exchangeOracle,
uint8 reputationOracleFeePercentage,
uint8 recordingOracleFeePercentage,
uint8 exchangeOracleFeePercentage
);
event BulkTransfer(
uint256 indexed txId,
address[] recipients,
Expand Down Expand Up @@ -72,12 +91,13 @@ contract Escrow is IEscrow, ReentrancyGuard {
address public immutable admin;
address public immutable escrowFactory;
address public immutable token;
address public immutable kvstore;

uint8 public reputationOracleFeePercentage;
uint8 public recordingOracleFeePercentage;
uint8 public exchangeOracleFeePercentage;

string public manifestUrl;
string public manifest;
string public manifestHash;
string public intermediateResultsUrl;
string public intermediateResultsHash;
Expand All @@ -94,21 +114,25 @@ contract Escrow is IEscrow, ReentrancyGuard {
* @param _launcher Creator of the escrow.
* @param _admin Admin address for the escrow.
* @param _duration Escrow lifetime (seconds).
* @param _kvstore KVStore contract address.
*/
constructor(
address _token,
address _launcher,
address _admin,
uint256 _duration
uint256 _duration,
address _kvstore
) {
require(_launcher != address(0), ERROR_ZERO_ADDRESS);
require(_admin != address(0), ERROR_ZERO_ADDRESS);
require(_token != address(0), ERROR_ZERO_ADDRESS);
require(_kvstore != address(0), ERROR_ZERO_ADDRESS);
require(_duration > 0, 'Duration is 0');

token = _token;
launcher = _launcher;
admin = _admin;
kvstore = _kvstore;
escrowFactory = msg.sender;

status = EscrowStatuses.Launched;
Expand All @@ -135,30 +159,24 @@ contract Escrow is IEscrow, ReentrancyGuard {
* @param _reputationOracle Address of the reputation oracle.
* @param _recordingOracle Address of the recording oracle.
* @param _exchangeOracle Address of the exchange oracle.
* @param _reputationOracleFeePercentage Fee percentage for the reputation oracle.
* @param _recordingOracleFeePercentage Fee percentage for the recording oracle.
* @param _exchangeOracleFeePercentage Fee percentage for the exchange oracle.
* @param _url URL for the escrow manifest.
* @param _hash Hash of the escrow manifest.
* @param _manifest Manifest or URL for the escrow manifest.
* @param _manifestHash Hash of the escrow manifest.
*/
function setup(
address _reputationOracle,
address _recordingOracle,
address _exchangeOracle,
uint8 _reputationOracleFeePercentage,
uint8 _recordingOracleFeePercentage,
uint8 _exchangeOracleFeePercentage,
string calldata _url,
string calldata _hash
string calldata _manifest,
string calldata _manifestHash
) external override adminLauncherOrFactory notExpired {
require(_reputationOracle != address(0), 'Invalid reputation oracle');
require(_recordingOracle != address(0), 'Invalid recording oracle');
require(_exchangeOracle != address(0), 'Invalid exchange oracle');

uint256 totalFeePercentage = _reputationOracleFeePercentage +
_recordingOracleFeePercentage +
_exchangeOracleFeePercentage;
require(totalFeePercentage <= 100, 'Percentage out of bounds');
uint8 _reputationOracleFeePercentage = _getOracleFee(_reputationOracle);
uint8 _recordingOracleFeePercentage = _getOracleFee(_recordingOracle);
uint8 _exchangeOracleFeePercentage = _getOracleFee(_exchangeOracle);

require(status == EscrowStatuses.Launched, 'Wrong status');

reputationOracle = _reputationOracle;
Expand All @@ -169,23 +187,45 @@ contract Escrow is IEscrow, ReentrancyGuard {
recordingOracleFeePercentage = _recordingOracleFeePercentage;
exchangeOracleFeePercentage = _exchangeOracleFeePercentage;

manifestUrl = _url;
manifestHash = _hash;
manifest = _manifest;
manifestHash = _manifestHash;
status = EscrowStatuses.Pending;

remainingFunds = getBalance();
require(remainingFunds > 0, 'Zero balance');

emit PendingV2(
_url,
_hash,
emit PendingV3(
_manifest,
_manifestHash,
_reputationOracle,
_recordingOracle,
_exchangeOracle
_exchangeOracle,
_reputationOracleFeePercentage,
_recordingOracleFeePercentage,
_exchangeOracleFeePercentage
);
emit Fund(remainingFunds);
}

function _getOracleFee(address _oracle) private view returns (uint8) {
return _parseUint8(IKVStore(kvstore).get(_oracle, FEE_KEY));
}

function _parseUint8(string memory _value) private pure returns (uint8) {
bytes memory valueBytes = bytes(_value);
require(valueBytes.length > 0, 'Invalid oracle fee');

uint256 parsedValue = 0;
for (uint256 i = 0; i < valueBytes.length; i++) {
uint8 c = uint8(valueBytes[i]);
require(c >= 48 && c <= 57, 'Invalid oracle fee');
parsedValue = parsedValue * 10 + (c - 48);
require(parsedValue <= MAX_ORACLE_FEE, 'Percentage out of bounds');
}

return uint8(parsedValue);
}

/**
* @dev Initiates a cancellation request. If expired, it finalizes immediately.
*/
Expand Down
30 changes: 18 additions & 12 deletions packages/core/contracts/EscrowFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
address public staking;
uint256 public minimumStake;
address public admin;
address public kvstore;

using SafeERC20 for IERC20;

event Launched(address token, address escrow);
event LaunchedV2(address token, address escrow, string jobRequesterId);
event SetStakingAddress(address indexed stakingAddress);
event SetMinumumStake(uint256 indexed minimumStake);
event SetKVStoreAddress(address indexed kvStoreAddress);

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
Expand All @@ -35,10 +37,12 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {

function initialize(
address _staking,
uint256 _minimumStake
uint256 _minimumStake,
address _kvstore
) external payable virtual initializer {
__Ownable_init_unchained();
require(_staking != address(0), ERROR_ZERO_ADDRESS);
_setKVStoreAddress(_kvstore);
_setStakingAddress(_staking);
_setMinimumStake(_minimumStake);
_setEscrowAdmin(msg.sender);
Expand All @@ -58,7 +62,8 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
_token,
msg.sender,
admin,
STANDARD_DURATION
STANDARD_DURATION,
kvstore
);
counter++;
escrowCounters[address(escrow)] = counter;
Expand Down Expand Up @@ -92,9 +97,6 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
* @param _reputationOracle Address of the reputation oracle.
* @param _recordingOracle Address of the recording oracle.
* @param _exchangeOracle Address of the exchange oracle.
* @param _reputationOracleFeePercentage Fee percentage for the reputation oracle.
* @param _recordingOracleFeePercentage Fee percentage for the recording oracle.
* @param _exchangeOracleFeePercentage Fee percentage for the exchange oracle.
* @param _url URL for the escrow manifest.
* @param _hash Hash of the escrow manifest.
* @return The address of the newly created Escrow contract.
Expand All @@ -106,9 +108,6 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
address _reputationOracle,
address _recordingOracle,
address _exchangeOracle,
uint8 _reputationOracleFeePercentage,
uint8 _recordingOracleFeePercentage,
uint8 _exchangeOracleFeePercentage,
string calldata _url,
string calldata _hash
) external returns (address) {
Expand All @@ -124,9 +123,6 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
_reputationOracle,
_recordingOracle,
_exchangeOracle,
_reputationOracleFeePercentage,
_recordingOracleFeePercentage,
_exchangeOracleFeePercentage,
_url,
_hash
);
Expand Down Expand Up @@ -179,12 +175,22 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable {
admin = _admin;
}

function setKVStoreAddress(address _kvstore) external onlyOwner {
_setKVStoreAddress(_kvstore);
}

function _setKVStoreAddress(address _kvstore) private {
require(_kvstore != address(0), ERROR_ZERO_ADDRESS);
kvstore = _kvstore;
emit SetKVStoreAddress(_kvstore);
}

function _authorizeUpgrade(address) internal override onlyOwner {}

/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[44] private __gap;
uint256[43] private __gap;
}
7 changes: 2 additions & 5 deletions packages/core/contracts/interfaces/IEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ interface IEscrow {
address _reputationOracle,
address _recordingOracle,
address _exchangeOracle,
uint8 _reputationOracleFeePercentage,
uint8 _recordingOracleFeePercentage,
uint8 _exchangeOracleFeePercentage,
string calldata _url,
string calldata _hash
string calldata _manifest,
string calldata _manifestHash
) external;

function requestCancellation() external;
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 @@ -12,6 +12,7 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable {
// all Escrows will have this duration.
uint256 constant STANDARD_DURATION = 8640000;
string constant ERROR_ZERO_ADDRESS = 'EscrowFactory: Zero Address';
address constant DUMMY_KVSTORE = address(1);

uint256 public counter;
mapping(address => uint256) public escrowCounters;
Expand Down Expand Up @@ -64,8 +65,9 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable {
Escrow escrow = new Escrow(
token,
msg.sender,
payable(msg.sender),
STANDARD_DURATION
msg.sender,
STANDARD_DURATION,
DUMMY_KVSTORE
);
counter++;
escrowCounters[address(escrow)] = counter;
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"ts-node": "^10.9.2",
"typechain": "^8.3.2",
"typescript": "^5.8.3",
"typescript-eslint": "^8.39.1",
"xdeployer": "3.1.6"
},
"peerDependencies": {
Expand Down
19 changes: 7 additions & 12 deletions packages/core/scripts/deploy-proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
import { ethers, upgrades } from 'hardhat';

async function main() {
const hmtAddress = process.env.HMT_ADDRESS;
if (!hmtAddress) {
console.error('HMT_ADDRESS env variable missing');
return;
}

const stakingAddress = process.env.STAKING_ADDRESS;
if (!stakingAddress) {
console.error('STAKING_ADDRESS env variable missing');
return;
}

const kvStoreAddress = process.env.KVSTORE_ADDRESS;
if (!kvStoreAddress) {
console.error('KVSTORE_ADDRESS env variable missing');
return;
}

const EscrowFactory = await ethers.getContractFactory(
'contracts/EscrowFactory.sol:EscrowFactory'
);
const escrowFactoryContract = await upgrades.deployProxy(
EscrowFactory,
[stakingAddress, 1],
[stakingAddress, 1, kvStoreAddress],
{ initializer: 'initialize', kind: 'uups' }
);
await escrowFactoryContract.waitForDeployment();
Expand All @@ -33,11 +33,6 @@ async function main() {
await escrowFactoryContract.getAddress()
)
);

const KVStore = await ethers.getContractFactory('KVStore');
const kvStoreContract = await KVStore.deploy();

console.log('KVStore Address: ', await kvStoreContract.getAddress());
}

main().catch((error) => {
Expand Down
Loading
Loading