-
Notifications
You must be signed in to change notification settings - Fork 11
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
App <-> bridge #98
App <-> bridge #98
Changes from all commits
44fef54
5ac78e5
e71fbdd
176daed
8f83aeb
40967b3
e596bf1
eacb9b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,14 +10,14 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; | ||
import "@threshold/contracts/staking/IApplication.sol"; | ||
import "@threshold/contracts/staking/IStaking.sol"; | ||
import "./Adjudicator.sol"; | ||
import "./coordination/IUpdatableStakeInfo.sol"; | ||
|
||
|
||
/** | ||
* @title PRE Application | ||
* @title TACo Application | ||
* @notice Contract distributes rewards for participating in app and slashes for violating rules | ||
*/ | ||
contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | ||
contract TACoApplication is IApplication, OwnableUpgradeable { | ||
|
||
using SafeERC20 for IERC20; | ||
using SafeCast for uint256; | ||
|
@@ -132,6 +132,9 @@ contract PREApplication 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; | ||
|
@@ -148,10 +151,6 @@ contract PREApplication 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 _minimumAuthorization 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 | ||
|
@@ -160,22 +159,11 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
constructor( | ||
IERC20 _token, | ||
IStaking _tStaking, | ||
SignatureVerifier.HashAlgorithm _hashAlgorithm, | ||
uint256 _basePenalty, | ||
uint256 _penaltyHistoryCoefficient, | ||
uint256 _percentagePenaltyCoefficient, | ||
uint96 _minimumAuthorization, | ||
uint256 _minOperatorSeconds, | ||
uint256 _rewardDuration, | ||
uint256 _deauthorizationDuration | ||
) | ||
Adjudicator( | ||
_hashAlgorithm, | ||
_basePenalty, | ||
_penaltyHistoryCoefficient, | ||
_percentagePenaltyCoefficient | ||
) | ||
{ | ||
) { | ||
require( | ||
_rewardDuration != 0 && | ||
_tStaking.authorizedStake(address(this), address(this)) == 0 && | ||
|
@@ -228,6 +216,26 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
__Ownable_init(); | ||
} | ||
|
||
/** | ||
* @notice Set contract for multi-chain interactions | ||
*/ | ||
function setUpdatableStakeInfo(IUpdatableStakeInfo _updatableStakeInfo) external onlyOwner { | ||
require(address(_updatableStakeInfo) != address(updatableStakeInfo), "New address must not be equal to the current one"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need this check? What's the worst can happen? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. considering that is method for DAO - I prefer to more checks than less in any case |
||
if (address(_updatableStakeInfo) != address(0)) { | ||
// trying to call contract to be sure that is correct address | ||
_updatableStakeInfo.updateOperator(address(0), address(0)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this is to implicitly check the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and to check that contract is correct one in general |
||
} | ||
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------------------------------ | ||
|
||
/** | ||
|
@@ -341,8 +349,8 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
/** | ||
* @notice Recalculate reward and save increased authorization. Can be called only by staking contract | ||
* @param _stakingProvider Address of staking provider | ||
* @param _fromAmount Amount of previously authorized tokens to PRE application by staking provider | ||
* @param _toAmount Amount of authorized tokens to PRE application by staking provider | ||
* @param _fromAmount Amount of previously authorized tokens to TACo application by staking provider | ||
* @param _toAmount Amount of authorized tokens to TACo application by staking provider | ||
*/ | ||
function authorizationIncreased( | ||
address _stakingProvider, | ||
|
@@ -368,6 +376,7 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
|
||
info.authorized = _toAmount; | ||
emit AuthorizationIncreased(_stakingProvider, _fromAmount, _toAmount); | ||
_updateAuthorization(_stakingProvider, info); | ||
} | ||
|
||
/** | ||
|
@@ -398,8 +407,9 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
if (info.authorized == 0) { | ||
_stakingProviderFromOperator[info.operator] = address(0); | ||
info.operator = address(0); | ||
info.operatorConfirmed == false; | ||
_releaseOperator(_stakingProvider); | ||
} | ||
_updateAuthorization(_stakingProvider, info); | ||
} | ||
|
||
/** | ||
|
@@ -429,6 +439,7 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
info.deauthorizing = _fromAmount - _toAmount; | ||
info.endDeauthorization = uint64(block.timestamp + deauthorizationDuration); | ||
emit AuthorizationDecreaseRequested(_stakingProvider, _fromAmount, _toAmount); | ||
_updateAuthorization(_stakingProvider, info); | ||
} | ||
|
||
/** | ||
|
@@ -454,8 +465,9 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
if (info.authorized == 0) { | ||
_stakingProviderFromOperator[info.operator] = address(0); | ||
info.operator = address(0); | ||
info.operatorConfirmed == false; | ||
_releaseOperator(_stakingProvider); | ||
} | ||
_updateAuthorization(_stakingProvider, info); | ||
} | ||
|
||
/** | ||
|
@@ -480,15 +492,16 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
if (info.authorized == 0) { | ||
_stakingProviderFromOperator[info.operator] = address(0); | ||
info.operator = address(0); | ||
info.operatorConfirmed == false; | ||
_releaseOperator(_stakingProvider); | ||
} | ||
_updateAuthorization(_stakingProvider, info); | ||
} | ||
|
||
//-------------------------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]; | ||
} | ||
|
||
|
@@ -502,10 +515,17 @@ contract PREApplication 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; | ||
} | ||
|
||
/** | ||
* @notice Get all tokens delegated to the staking provider | ||
*/ | ||
function getEligibleAmount(StakingProviderInfo storage _info) internal view returns (uint96) { | ||
return _info.authorized - _info.deauthorizing; | ||
} | ||
|
||
/** | ||
* @notice Get the value of authorized tokens for active providers as well as providers and their authorized tokens | ||
* @param _startIndex Start index for looking in providers array | ||
|
@@ -531,7 +551,7 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
for (uint256 i = _startIndex; i < endIndex; i++) { | ||
address stakingProvider = stakingProviders[i]; | ||
StakingProviderInfo storage info = stakingProviderInfo[stakingProvider]; | ||
uint256 eligibleAmount = info.authorized - info.deauthorizing; | ||
uint256 eligibleAmount = getEligibleAmount(info); | ||
if (eligibleAmount < minimumAuthorization || !info.operatorConfirmed) { | ||
continue; | ||
} | ||
|
@@ -618,8 +638,8 @@ contract PREApplication is IApplication, Adjudicator, OwnableUpgradeable { | |
// Bond new operator (or unbond if _operator == address(0)) | ||
info.operator = _operator; | ||
info.operatorStartTimestamp = uint64(block.timestamp); | ||
info.operatorConfirmed = false; | ||
emit OperatorBonded(_stakingProvider, _operator, previousOperator, block.timestamp); | ||
_releaseOperator(_stakingProvider); | ||
} | ||
|
||
/** | ||
|
@@ -636,6 +656,33 @@ contract PREApplication 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); | ||
} | ||
} | ||
|
||
//-------------------------XChain------------------------- | ||
|
||
/** | ||
* @notice Resets operator confirmation | ||
*/ | ||
function _releaseOperator(address _stakingProvider) internal { | ||
stakingProviderInfo[_stakingProvider].operatorConfirmed = false; | ||
if (address(updatableStakeInfo) != address(0)) { | ||
updatableStakeInfo.updateOperator(_stakingProvider, address(0)); | ||
} | ||
} | ||
|
||
/** | ||
* @notice Send updated authorized amount to xchain contract | ||
*/ | ||
function _updateAuthorization(address _stakingProvider, StakingProviderInfo storage _info) internal { | ||
if (address(updatableStakeInfo) != address(0)) { | ||
// TODO send both authorized and eligible amounts in case of slashing from StakeInfo | ||
uint96 eligibleAmount = getEligibleAmount(_info); | ||
updatableStakeInfo.updateAmount(_stakingProvider, eligibleAmount); | ||
} | ||
} | ||
|
||
//-------------------------Slashing------------------------- | ||
|
@@ -650,8 +697,9 @@ contract PREApplication 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); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems
Adjudicator
is not upgradeable anymore, right? In that case, theuint256[50] private reservedSlots;
in L46 should be removed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly,
Adjudicator
needs reincarnation but I guess it's not time. So I'll remove those fields but ideally make it upgradeableThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have a
setAdjudicator()
method in the app, do we really need it to be upgradeable? We can just deploy a new version and set it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjudicator has some state that ideally to preserve. For example, history to not slash twice for the same misbehavior. That's main reason to make it upreadable with the current design
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracking issue here: #100