Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/reputation contract #172

Merged
merged 20 commits into from
Jan 23, 2023
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
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { Grid, Typography } from '@mui/material';
import { Grid } from '@mui/material';
import * as React from 'react';
import { CardTextBlock } from 'src/components/Cards';
import BitfinexIcon from 'src/components/Icons/BitfinexIcon';
portuu3 marked this conversation as resolved.
Show resolved Hide resolved
import useBitfinexTicker from 'src/hooks/useBitfinexTicker';
import { useTokenStatsByChainId } from 'src/state/token/hooks';

export const TokenView: React.FC = (): React.ReactElement => {
const { totalTransferEventCount, holders, totalSupply } =
useTokenStatsByChainId();
const bitfinexTicker = useBitfinexTicker();

return (
<Grid container spacing={{ xs: 2, sm: 2, md: 3, lg: 4, xl: 5 }}>
Expand Down
27 changes: 21 additions & 6 deletions packages/core/contracts/Escrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ contract Escrow is IEscrow {

string public manifestUrl;
string public manifestHash;
uint256 public remainingFortunes;

string public finalResultsUrl;
string public finalResultsHash;
Expand Down Expand Up @@ -93,7 +94,8 @@ contract Escrow is IEscrow {
uint256 _reputationOracleStake,
uint256 _recordingOracleStake,
string memory _url,
string memory _hash
string memory _hash,
uint256 _fortunesRequested
) public trusted notExpired {
require(
_reputationOracle != address(0),
Expand All @@ -103,6 +105,7 @@ contract Escrow is IEscrow {
_recordingOracle != address(0),
'Invalid or missing token spender'
);
require(_fortunesRequested > 0, 'Invalid or missing fortunes');
uint256 totalStake = _reputationOracleStake.add(_recordingOracleStake);
require(totalStake >= 0 && totalStake <= 100, 'Stake out of bounds');
require(
Expand All @@ -120,6 +123,7 @@ contract Escrow is IEscrow {

manifestUrl = _url;
manifestHash = _hash;
remainingFortunes = _fortunesRequested;
status = EscrowStatuses.Pending;
emit Pending(manifestUrl, manifestHash);
}
Expand Down Expand Up @@ -213,11 +217,22 @@ contract Escrow is IEscrow {

bulkPaid = true;
balance = getBalance();
if (status == EscrowStatuses.Pending) {
status = EscrowStatuses.Partial;
}
if (balance == 0 && status == EscrowStatuses.Partial) {
status = EscrowStatuses.Paid;
if (bulkPaid) {
if (status == EscrowStatuses.Pending) {
status = EscrowStatuses.Partial;
remainingFortunes = remainingFortunes.sub(_recipients.length);
}
if (
balance > 0 &&
status == EscrowStatuses.Partial &&
remainingFortunes == 0
) {
_safeTransfer(canceler, balance);
portuu3 marked this conversation as resolved.
Show resolved Hide resolved
status = EscrowStatuses.Paid;
}
if (balance == 0 && status == EscrowStatuses.Partial) {
status = EscrowStatuses.Paid;
}
}
emit BulkTransfer(_txId, _recipients.length);
return true;
Expand Down
134 changes: 134 additions & 0 deletions packages/core/contracts/Reputation.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;

import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import './utils/SignedSafeMath.sol';
import './interfaces/IStaking.sol';

contract Reputation is OwnableUpgradeable, UUPSUpgradeable {
using SignedSafeMath for int256;
using Stakes for Stakes.Staker;

struct Worker {
address workerAddress;
int256 reputation;
}

// Staking contract address
address public staking;
uint256 public minimumStake;

int256 private constant MIN_REPUTATION = 1;
int256 private constant MAX_REPUTATION = 100;
mapping(address => int256) public reputations;

function initialize(
address _staking,
uint256 _minimumStake
) external payable virtual initializer {
__Ownable_init_unchained();
__Reputation_init_unchained(_staking, _minimumStake);
}

function __Reputation_init_unchained(
address _staking,
uint256 _minimumStake
) internal onlyInitializing {
require(_staking != address(0), 'Zero address provided');
staking = _staking;
_setMinimumStake(_minimumStake);
}

function addReputations(Worker[] memory _workers) public {
Stakes.Staker memory staker = IStaking(staking).getStaker(msg.sender);
require(
staker.tokensAvailable() > minimumStake,
'Needs to stake HMT tokens to modify reputations.'
);

for (uint256 i = 0; i < _workers.length; i++) {
if (
reputations[_workers[i].workerAddress].add(
_workers[i].reputation
) >
MAX_REPUTATION ||
(reputations[_workers[i].workerAddress] == 0 &&
_workers[i].reputation.add(50) > MAX_REPUTATION)
) {
reputations[_workers[i].workerAddress] = MAX_REPUTATION;
} else if (
(reputations[_workers[i].workerAddress] == 0 &&
_workers[i].reputation.add(50) < MIN_REPUTATION) ||
(reputations[_workers[i].workerAddress].add(
_workers[i].reputation
) <
MIN_REPUTATION &&
reputations[_workers[i].workerAddress] != 0)
) {
reputations[_workers[i].workerAddress] = MIN_REPUTATION;
} else {
if (reputations[_workers[i].workerAddress] == 0) {
reputations[_workers[i].workerAddress] = _workers[i]
.reputation
.add(50);
} else {
reputations[_workers[i].workerAddress] = reputations[
_workers[i].workerAddress
].add(_workers[i].reputation);
}
}
}
}

function getReputations(
address[] memory _workers
) public view returns (Worker[] memory) {
Worker[] memory returnedValues = new Worker[](_workers.length);

for (uint256 i = 0; i < _workers.length; i++) {
returnedValues[i] = Worker(_workers[i], reputations[_workers[i]]);
}

return returnedValues;
}

function getRewards(
int256 balance,
address[] memory _workers
) public view returns (int256[] memory) {
int256[] memory returnedValues = new int256[](_workers.length);
int256 totalReputation = 0;

for (uint256 i = 0; i < _workers.length; i++) {
totalReputation = totalReputation.add(reputations[_workers[i]]);
}

for (uint256 i = 0; i < _workers.length; i++) {
returnedValues[i] = balance.mul(reputations[_workers[i]]).div(
totalReputation
);
}

return returnedValues;
}

function setMinimumStake(uint256 _minimumStake) external onlyOwner {
_setMinimumStake(_minimumStake);
}

function _setMinimumStake(uint256 _minimumStake) private {
require(_minimumStake > 0, 'Must be a positive number');
minimumStake = _minimumStake;
}

// solhint-disable-next-line no-empty-blocks
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[43] private __gap;
}
3 changes: 2 additions & 1 deletion packages/core/contracts/interfaces/IEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ interface IEscrow {
uint256 _reputationOracleStake,
uint256 _recordingOracleStake,
string memory _url,
string memory _hash
string memory _hash,
uint256 _fortunesRequested
) external;

function abort() external;
Expand Down
114 changes: 114 additions & 0 deletions packages/core/contracts/test/ReputationV0.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;

import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import '../utils/SignedSafeMath.sol';
import '../interfaces/IStaking.sol';

contract ReputationV0 is OwnableUpgradeable, UUPSUpgradeable {
using SignedSafeMath for int256;
using Stakes for Stakes.Staker;

struct Worker {
address workerAddress;
int256 reputation;
}

// Staking contract address
address public staking;
uint256 public minimumStake;

int256 private constant MIN_REPUTATION = 1;
int256 private constant MAX_REPUTATION = 100;
mapping(address => int256) public reputations;

function initialize(
address _staking,
uint256 _minimumStake
) external payable virtual initializer {
__Ownable_init_unchained();
__Reputation_init_unchained(_staking, _minimumStake);
}

function __Reputation_init_unchained(
address _staking,
uint256 _minimumStake
) internal onlyInitializing {
require(_staking != address(0), 'Zero address provided');
staking = _staking;
_setMinimumStake(_minimumStake);
}

function addReputations(Worker[] memory _workers) public {
Stakes.Staker memory staker = IStaking(staking).getStaker(msg.sender);
require(
staker.tokensAvailable() > minimumStake,
'Needs to stake HMT tokens to modify reputations.'
);

for (uint256 i = 0; i < _workers.length; i++) {
if (
reputations[_workers[i].workerAddress].add(
_workers[i].reputation
) >
MAX_REPUTATION ||
(reputations[_workers[i].workerAddress] == 0 &&
_workers[i].reputation.add(50) > MAX_REPUTATION)
) {
reputations[_workers[i].workerAddress] = MAX_REPUTATION;
} else if (
(reputations[_workers[i].workerAddress] == 0 &&
_workers[i].reputation.add(50) < MIN_REPUTATION) ||
(reputations[_workers[i].workerAddress].add(
_workers[i].reputation
) <
MIN_REPUTATION &&
reputations[_workers[i].workerAddress] != 0)
) {
reputations[_workers[i].workerAddress] = MIN_REPUTATION;
} else {
if (reputations[_workers[i].workerAddress] == 0) {
reputations[_workers[i].workerAddress] = _workers[i]
.reputation
.add(50);
} else {
reputations[_workers[i].workerAddress] = reputations[
_workers[i].workerAddress
].add(_workers[i].reputation);
}
}
}
}

function getReputations(
address[] memory _workers
) public view returns (Worker[] memory) {
Worker[] memory returnedValues = new Worker[](_workers.length);

for (uint256 i = 0; i < _workers.length; i++) {
returnedValues[i] = Worker(_workers[i], reputations[_workers[i]]);
}

return returnedValues;
}

function setMinimumStake(uint256 _minimumStake) external onlyOwner {
_setMinimumStake(_minimumStake);
}

function _setMinimumStake(uint256 _minimumStake) private {
require(_minimumStake > 0, 'Must be a positive number');
minimumStake = _minimumStake;
}

// solhint-disable-next-line no-empty-blocks
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[43] private __gap;
}
Loading