Skip to content
Draft
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
18 changes: 18 additions & 0 deletions contracts/contracts/TACoApplication.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol";
import "./coordination/ITACoRootToChild.sol";
import "./coordination/ITACoChildToRoot.sol";
import "./coordination/PenaltyBoard.sol";

/**
* @title TACo Application
Expand Down Expand Up @@ -142,6 +143,7 @@ contract TACoApplication is ITACoChildToRoot, OwnableUpgradeable {

// mapping(address => bool) public stakingProviderReleased;
// mapping(address => bool) public allowList;
PenaltyBoard public penaltyBoard;

/**
* @notice Constructor sets address of token contract and parameters for staking
Expand Down Expand Up @@ -185,6 +187,14 @@ contract TACoApplication is ITACoChildToRoot, OwnableUpgradeable {
childApplication = _childApplication;
}

/**
* @notice Set contract for compensation
*/
function setPenaltyBoard(PenaltyBoard _penaltyBoard) external onlyOwner {
require(address(_penaltyBoard).code.length > 0, "PenaltyBoard must be contract");
penaltyBoard = _penaltyBoard;
}

//------------------------Staking------------------------------

function initializeStake(
Expand Down Expand Up @@ -439,6 +449,7 @@ contract TACoApplication is ITACoChildToRoot, OwnableUpgradeable {
info.operatorStartTimestamp = uint64(block.timestamp);
emit OperatorBonded(_stakingProvider, _operator, previousOperator, block.timestamp);

penaltyBoard.computeRewards(_stakingProvider);
info.operatorConfirmed = false;
childApplication.updateOperator(_stakingProvider, _operator);
}
Expand All @@ -460,6 +471,7 @@ contract TACoApplication is ITACoChildToRoot, OwnableUpgradeable {

StakingProviderInfo storage info = stakingProviderInfo[stakingProvider];
if (!info.operatorConfirmed) {
penaltyBoard.enableRewards(stakingProvider);
info.operatorConfirmed = true;
emit OperatorConfirmed(stakingProvider, _operator);
}
Expand All @@ -471,6 +483,7 @@ contract TACoApplication is ITACoChildToRoot, OwnableUpgradeable {
* @notice Resets operator confirmation
*/
function _releaseOperator(address _stakingProvider) internal {
penaltyBoard.computeRewards(_stakingProvider);
StakingProviderInfo storage info = stakingProviderInfo[_stakingProvider];
_stakingProviderFromOperator[info.operator] = address(0);
info.operator = address(0);
Expand Down Expand Up @@ -555,4 +568,9 @@ contract TACoApplication is ITACoChildToRoot, OwnableUpgradeable {
emit StakelessProviderAdded(_stakingProvider);
token.safeTransfer(info.owner, authorized);
}

function isEligibleForReward(address _stakingProvider) external view returns (bool) {
StakingProviderInfo storage info = stakingProviderInfo[_stakingProvider];
return !info.stakeless && info.operatorConfirmed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.0;

/**
* @title ITACoApplicationForPenaltyBoard
* @notice Minimal view interface that PenaltyBoard (with compensation) needs from TACoApplication.
* Used for withdrawal auth (owner, beneficiary), payout address (beneficiary), and stakeless check.
*/
interface ITACoApplicationForPenaltyBoard {
/**
* @notice Returns beneficiary for a staking provider (tokens are sent here on withdraw).
* Assumed never zero for a registered staking provider.
*/
function getBeneficiary(
address stakingProvider
) external view returns (address payable beneficiary);

/**
* @notice Returns owner and beneficiary for a staking provider.
* Withdraw(stakingProvider) may be called by stakingProvider, owner, or beneficiary.
* Matches TACoApplication.rolesOf.
*/
function rolesOf(
address stakingProvider
) external view returns (address owner, address beneficiary);

/**
* @notice Returns true if the staking provider is stakeless (compensation = 0).
* If not present on TACoApplication, implementation may return false.
*/
function isStakeless(address stakingProvider) external view returns (bool);

/**
* @notice Returns true if staking provider eligible for reward.
*/
function isEligibleForReward(address _stakingProvider) external view returns (bool);
}
Loading
Loading