Skip to content

Commit

Permalink
Extracts Adjudicator from application to decrease contract size, fixe…
Browse files Browse the repository at this point in the history
…s bug with releasing operator
  • Loading branch information
vzotova committed Jul 10, 2023
1 parent 3c47c10 commit 335494d
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
run: ape run scripts/deploy_nucypher_token.py --network ethereum:local

- name: Deploy PRE Application
run: ape run scripts/deploy_pre_application.py --network ethereum:local
run: ape run scripts/deploy_pre_cbd_application.py --network ethereum:local

- name: Deploy Staking Escrow
run: ape run scripts/deploy_staking_escrow.py --network ethereum:local
Expand Down
40 changes: 13 additions & 27 deletions contracts/contracts/Adjudicator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import "./lib/ReEncryptionValidator.sol";
import "./lib/SignatureVerifier.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "./PRECBDApplication.sol";


/**
* @title Adjudicator
* @notice Supervises operators' behavior and punishes when something's wrong.
* @dev |v3.1.1|
*/
abstract contract Adjudicator {
contract Adjudicator {

using UmbralDeserializer for bytes;
using SafeCast for uint256;
Expand All @@ -37,6 +38,7 @@ abstract contract Adjudicator {
uint256 public immutable basePenalty;
uint256 public immutable penaltyHistoryCoefficient;
uint256 public immutable percentagePenaltyCoefficient;
PRECBDApplication public immutable application;

mapping (address => uint256) public penaltyHistory;
mapping (bytes32 => bool) public evaluatedCFrags;
Expand All @@ -50,16 +52,22 @@ abstract contract Adjudicator {
* @param _percentagePenaltyCoefficient Coefficient for calculating the percentage penalty
*/
constructor(
PRECBDApplication _application,
SignatureVerifier.HashAlgorithm _hashAlgorithm,
uint256 _basePenalty,
uint256 _penaltyHistoryCoefficient,
uint256 _percentagePenaltyCoefficient
) {
require(_percentagePenaltyCoefficient != 0, "Wrong input parameters");
require(
_percentagePenaltyCoefficient != 0 &&
address(_application.token()) != address(0),
"Wrong input parameters"
);
hashAlgorithm = _hashAlgorithm;
basePenalty = _basePenalty;
percentagePenaltyCoefficient = _percentagePenaltyCoefficient;
penaltyHistoryCoefficient = _penaltyHistoryCoefficient;
application = _application;
}

/**
Expand Down Expand Up @@ -146,17 +154,17 @@ abstract contract Adjudicator {
address operator = SignatureVerifier.recover(
SignatureVerifier.hashEIP191(stamp, bytes1(0x45)), // Currently, we use version E (0x45) of EIP191 signatures
_operatorIdentityEvidence);
address stakingProvider = stakingProviderFromOperator(operator);
address stakingProvider = application.stakingProviderFromOperator(operator);
require(stakingProvider != address(0), "Operator must be related to a provider");

// 5. Check that staking provider can be slashed
uint96 stakingProviderValue = authorizedStake(stakingProvider);
uint96 stakingProviderValue = application.authorizedStake(stakingProvider);
require(stakingProviderValue > 0, "Provider has no tokens");

// 6. If CFrag was incorrect, slash staking provider
if (!cFragIsCorrect) {
uint96 penalty = calculatePenalty(stakingProvider, stakingProviderValue);
slash(stakingProvider, penalty, msg.sender);
application.slash(stakingProvider, penalty, msg.sender);
emit IncorrectCFragVerdict(evaluationHash, operator, stakingProvider);
}
}
Expand All @@ -176,26 +184,4 @@ abstract contract Adjudicator {
return penalty.toUint96();
}

/**
* @notice Get all tokens delegated to the staking provider
*/
function authorizedStake(address _stakingProvider) public view virtual returns (uint96);

/**
* @notice Get staking provider address bonded with specified operator address
*/
function stakingProviderFromOperator(address _operator) public view virtual returns (address);

/**
* @notice Slash the provider's stake and reward the investigator
* @param _stakingProvider Staking provider address
* @param _penalty Penalty
* @param _investigator Investigator
*/
function slash(
address _stakingProvider,
uint96 _penalty,
address _investigator
) internal virtual;

}
57 changes: 33 additions & 24 deletions contracts/contracts/PRECBDApplication.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol";
import "../threshold/IApplication.sol";
import "../threshold/IStaking.sol";
import "./Adjudicator.sol";
import "./coordination/IUpdatableStakeInfo.sol";


/**
* @title PRE+CBD Application
* @notice Contract distributes rewards for participating in app and slashes for violating rules
*/
contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
contract PRECBDApplication is IApplication, OwnableUpgradeable {

using SafeERC20 for IERC20;
using SafeCast for uint256;
Expand Down Expand Up @@ -133,7 +132,9 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {

IStaking public immutable tStaking;
IERC20 public immutable token;

IUpdatableStakeInfo public updatableStakeInfo;
address public adjudicator;

mapping (address => StakingProviderInfo) public stakingProviderInfo;
address[] public stakingProviders;
Expand All @@ -150,10 +151,6 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
* @notice Constructor sets address of token contract and parameters for staking
* @param _token T token contract
* @param _tStaking T token staking contract
* @param _hashAlgorithm Hashing algorithm
* @param _basePenalty Base for the penalty calculation
* @param _penaltyHistoryCoefficient Coefficient for calculating the penalty depending on the history
* @param _percentagePenaltyCoefficient Coefficient for calculating the percentage penalty
* @param _minAuthorization Amount of minimum allowable authorization
* @param _minOperatorSeconds Min amount of seconds while an operator can't be changed
* @param _rewardDuration Duration of one reward cycle
Expand All @@ -162,22 +159,11 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
constructor(
IERC20 _token,
IStaking _tStaking,
SignatureVerifier.HashAlgorithm _hashAlgorithm,
uint256 _basePenalty,
uint256 _penaltyHistoryCoefficient,
uint256 _percentagePenaltyCoefficient,
uint256 _minAuthorization,
uint256 _minOperatorSeconds,
uint256 _rewardDuration,
uint256 _deauthorizationDuration
)
Adjudicator(
_hashAlgorithm,
_basePenalty,
_penaltyHistoryCoefficient,
_percentagePenaltyCoefficient
)
{
) {
require(
_rewardDuration != 0 &&
_tStaking.authorizedStake(address(this), address(this)) == 0 &&
Expand Down Expand Up @@ -242,6 +228,14 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
updatableStakeInfo = _updatableStakeInfo;
}

/**
* @notice Set Set adjudicator contract. If zero then slashing is disabled
*/
function setAdjudicator(address _adjudicator) external onlyOwner {
require(address(_adjudicator) != address(adjudicator), "New address must not be equal to the current one");
adjudicator = _adjudicator;
}

//------------------------Reward------------------------------

/**
Expand Down Expand Up @@ -412,7 +406,8 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
if (info.authorized == 0) {
_stakingProviderFromOperator[info.operator] = address(0);
info.operator = address(0);
info.operatorConfirmed == false;
info.operatorConfirmed = false;
_releaseOperator(_stakingProvider);
}
}

Expand Down Expand Up @@ -468,7 +463,8 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
if (info.authorized == 0) {
_stakingProviderFromOperator[info.operator] = address(0);
info.operator = address(0);
info.operatorConfirmed == false;
info.operatorConfirmed = false;
_releaseOperator(_stakingProvider);
}
}

Expand All @@ -494,15 +490,16 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
if (info.authorized == 0) {
_stakingProviderFromOperator[info.operator] = address(0);
info.operator = address(0);
info.operatorConfirmed == false;
info.operatorConfirmed = false;
_releaseOperator(_stakingProvider);
}
}

//-------------------------Main-------------------------
/**
* @notice Returns staking provider for specified operator
*/
function stakingProviderFromOperator(address _operator) public view override returns (address) {
function stakingProviderFromOperator(address _operator) public view returns (address) {
return _stakingProviderFromOperator[_operator];
}

Expand All @@ -516,7 +513,7 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
/**
* @notice Get all tokens delegated to the staking provider
*/
function authorizedStake(address _stakingProvider) public view override returns (uint96) {
function authorizedStake(address _stakingProvider) public view returns (uint96) {
return stakingProviderInfo[_stakingProvider].authorized;
}

Expand Down Expand Up @@ -634,6 +631,7 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
info.operatorStartTimestamp = uint64(block.timestamp);
info.operatorConfirmed = false;
emit OperatorBonded(_stakingProvider, _operator, previousOperator, block.timestamp);
_releaseOperator(_stakingProvider);
}

/**
Expand All @@ -650,6 +648,16 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
info.operatorConfirmed = true;
authorizedOverall += info.authorized;
emit OperatorConfirmed(stakingProvider, msg.sender);

if (address(updatableStakeInfo) != address(0)) {
updatableStakeInfo.updateOperator(stakingProvider, msg.sender);
}
}

function _releaseOperator(address _stakingProvider) internal {
if (address(updatableStakeInfo) != address(0)) {
updatableStakeInfo.updateOperator(_stakingProvider, address(0));
}
}

//-------------------------Slashing-------------------------
Expand All @@ -664,8 +672,9 @@ contract PRECBDApplication is IApplication, Adjudicator, OwnableUpgradeable {
uint96 _penalty,
address _investigator
)
internal override
external
{
require(msg.sender == adjudicator, "Only adjudicator allowed to slash");
address[] memory stakingProviderWrapper = new address[](1);
stakingProviderWrapper[0] = _stakingProvider;
tStaking.seize(_penalty, 100, _investigator, stakingProviderWrapper);
Expand Down
18 changes: 4 additions & 14 deletions contracts/test/AdjudicatorTestSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,14 @@ import "../contracts/lib/SignatureVerifier.sol";
/**
* @notice Contract for testing the Adjudicator contract
*/
contract ExtendedAdjudicator is Adjudicator {
contract PRECBDApplicationForAdjudicatorMock {

uint32 public immutable secondsPerPeriod = 1;
mapping (address => uint96) public stakingProviderInfo;
mapping (address => uint256) public rewardInfo;
mapping (address => address) _stakingProviderFromOperator;

constructor(
SignatureVerifier.HashAlgorithm _hashAlgorithm,
uint256 _basePenalty,
uint256 _penaltyHistoryCoefficient,
uint256 _percentagePenaltyCoefficient
)
Adjudicator(_hashAlgorithm, _basePenalty, _penaltyHistoryCoefficient, _percentagePenaltyCoefficient)
{
}

function stakingProviderFromOperator(address _operator) public view override returns (address) {
function stakingProviderFromOperator(address _operator) public view returns (address) {
return _stakingProviderFromOperator[_operator];
}

Expand All @@ -40,7 +30,7 @@ contract ExtendedAdjudicator is Adjudicator {
_stakingProviderFromOperator[_operator] = _stakingProvider;
}

function authorizedStake(address _stakingProvider) public view override returns (uint96) {
function authorizedStake(address _stakingProvider) public view returns (uint96) {
return stakingProviderInfo[_stakingProvider];
}

Expand All @@ -49,7 +39,7 @@ contract ExtendedAdjudicator is Adjudicator {
uint96 _penalty,
address _investigator
)
internal override
external
{
stakingProviderInfo[_stakingProvider] -= _penalty;
rewardInfo[_investigator] += 1;
Expand Down
42 changes: 0 additions & 42 deletions contracts/test/PRECBDApplicationTestSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -168,45 +168,3 @@ contract Intermediary {
}

}


/**
* @notice Extended contract
*/
contract ExtendedPRECBDApplication is PRECBDApplication {

constructor(
IERC20 _token,
IStaking _tStaking,
SignatureVerifier.HashAlgorithm _hashAlgorithm,
uint256 _basePenalty,
uint256 _penaltyHistoryCoefficient,
uint256 _percentagePenaltyCoefficient,
uint256 _minAuthorization,
uint256 _minWorkerSeconds,
uint256 _rewardDuration,
uint256 _deauthorizationDuration
)
PRECBDApplication(
_token,
_tStaking,
_hashAlgorithm,
_basePenalty,
_penaltyHistoryCoefficient,
_percentagePenaltyCoefficient,
_minAuthorization,
_minWorkerSeconds,
_rewardDuration,
_deauthorizationDuration
)
{}

function testSlash(
address _stakingProvider,
uint96 _penalty,
address _investigator
) external {
slash(_stakingProvider, _penalty, _investigator);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ def main(account_id=None):
pre_app = project.PRECBDApplication.deploy(
t_token,
t_staking,
deployments_config.get("pre_hash_algorithm"),
deployments_config.get("pre_base_penalty"),
deployments_config.get("pre_penalty_history_coefficient"),
deployments_config.get("pre_percentage_penalty_coefficient"),
deployments_config.get("pre_min_authorization"),
deployments_config.get("pre_min_operator_seconds"),
deployments_config.get("reward_duration"),
Expand Down
Loading

0 comments on commit 335494d

Please sign in to comment.