Lucene search

K
code423n4Code4renaCODE423N4:2023-08-LIVEPEER-FINDINGS-ISSUES-154
HistorySep 06, 2023 - 12:00 a.m.

Slashing transcoders on violation should not effect the delegators who staked into such transcoders, delegators should continue to earn rewards

2023-09-0600:00:00
Code4rena
github.com
6
vulnerability
impact
delegators
rewards
resigning
transfer
logic
implementation
mitigation
review

Lines of code

Vulnerability details

Impact

Due to violation of norms, when a transcoder is slashed and force to resign, the delegators who provided stake into such transcoder should not be effected. They delegators should be able to continue earning the rewards as they delegated their tokens to protocol and not one specific transcoder.

But, when slashing is perform, the logic is not doing an lookup to see if the address of the transcoder
is assigned as delegatedAddess of the delegators and the delegated amount.

As the transcoder is resigned and take out of the pool, the transcoder will stop earning. So, as part of the resigning process, the delegators that were attached to the resigning transcoder should be moved to another active transcoder. Before doing so, the rewards applicable until the point of resigning should be claimed for the delegators.

The current implementation does not address this cases leading to delegators being attached to inactive transcoder effecting their rewards.

Proof of Concept

The below logic does not identify the delegators that are attached to the slashTranscoder and move the delegated amount to another active transcoder so that there is no impact on rewards for the delegator.

function slashTranscoder(
        address _transcoder,
        address _finder,
        uint256 _slashAmount,
        uint256 _finderFee
    ) external whenSystemNotPaused onlyVerifier autoClaimEarnings(_transcoder) autoCheckpoint(_transcoder) {
        Delegator storage del = delegators[_transcoder];

        if (del.bondedAmount > 0) {
            uint256 penalty = MathUtils.percOf(delegators[_transcoder].bondedAmount, _slashAmount);

            // If active transcoder, resign it
            if (transcoderPool.contains(_transcoder)) {
                resignTranscoder(_transcoder);
            }

            // Decrease bonded stake
            del.bondedAmount = del.bondedAmount.sub(penalty);

            // If still bonded decrease delegate's delegated amount
            if (delegatorStatus(_transcoder) == DelegatorStatus.Bonded) {
                delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(
                    penalty
                );
            }

            // Account for penalty
            uint256 burnAmount = penalty;

            // Award finder fee if there is a finder address
            if (_finder != address(0)) {
                uint256 finderAmount = MathUtils.percOf(penalty, _finderFee);
                minter().trustedTransferTokens(_finder, finderAmount);

                // Minter burns the slashed funds - finder reward
                minter().trustedBurnTokens(burnAmount.sub(finderAmount));

                emit TranscoderSlashed(_transcoder, _finder, penalty, finderAmount);
            } else {
                // Minter burns the slashed funds
                minter().trustedBurnTokens(burnAmount);

                emit TranscoderSlashed(_transcoder, address(0), penalty, 0);
            }
        } else {
            emit TranscoderSlashed(_transcoder, _finder, 0, 0);
        }
    }

Tools Used

Manual review

Recommended Mitigation Steps

Dev team to review this and implement the additional logic to transfer delegations to another active transcoder.

Assessed type

Other


The text was updated successfully, but these errors were encountered:

All reactions