sherlock-audit / 2024-01-telcoin-judging

6 stars 5 forks source link

s1l3nt - The owner of the TelcoinDistributor contract can freeze transactions/funds #7

Closed sherlock-admin2 closed 9 months ago

sherlock-admin2 commented 9 months ago

s1l3nt

high

The owner of the TelcoinDistributor contract can freeze transactions/funds

Summary

An integer overflow using the challengePeriod value can be used by the owner that deploys the TelcoinDistributor contract and through the challengePeriod value, he is able to freeze transactions any time he wishes and even get the funds stuck in the contract.

Vulnerability Detail

How challengePeriod is defined:

// amount of time a proposal can be challenged
uint256 public challengePeriod;

constructor(
        IERC20 telcoin,
        uint256 period,
        IERC721 council
    ) Ownable(_msgSender()) {
        // verifies no zero values were used
        require(
            address(telcoin) != address(0) &&
                address(council) != address(0) &&
                period != 0,
            "TelcoinDistributor: cannot intialize to zero"
        );
        // initialize telcoin address
        TELCOIN = telcoin;
        // Initialize challengePeriod duration
        challengePeriod = period;                    // [here]
        // Initialize councilNft address
        councilNft = council;
    [...]
function setChallengePeriod(uint256 newPeriod) public onlyOwner {
        //update period
        challengePeriod = newPeriod;
        // Emitting an event for new period
        emit ChallengePeriodUpdated(challengePeriod);
    }

challengeTransaction()

[...]
require(
            block.timestamp <=
                proposedTransactions[transactionId].timestamp + challengePeriod,
            "TelcoinDistributor: Challenge period has ended"
        );

// Sets the challenged flag of the proposed transaction to true
proposedTransactions[transactionId].challenged = true;

Using the challengePeriod, the require() check can evaluate to false any time he wishes. This will end up resulting on transactions that will never be challenged and executed, keeping in mind that the challenged flag will never be true, the function executeTransaction() will revert.

executeTransaction

 // Reverts if the challenge period has not expired
        // [1]
        require(                         
            block.timestamp >
                proposedTransactions[transactionId].timestamp + challengePeriod,
            "TelcoinDistributor: Challenge period has not ended"
        );

        // [2]
        // makes sure the transaction was not challenged
        require(
            !proposedTransactions[transactionId].challenged,
            "TelcoinDistributor: transaction has been challenged"
        );
        // makes sure the transaction was not executed previously
        require(
            !proposedTransactions[transactionId].executed,
            "TelcoinDistributor: transaction has been previously executed"
        );

    // sends out transaction
        batchTelcoin(...)
    [...]

At [1] that check will be false because of the overflow with challengePeriod. [2] reverts as well because the challengeTransaction() as shown above.

Impact

Code Snippet

https://github.com/sherlock-audit/2024-01-telcoin/blob/main/telcoin-audit/contracts/protocol/core/TelcoinDistributor.sol#L55 https://github.com/sherlock-audit/2024-01-telcoin/blob/main/telcoin-audit/contracts/protocol/core/TelcoinDistributor.sol#L115 https://github.com/sherlock-audit/2024-01-telcoin/blob/main/telcoin-audit/contracts/protocol/core/TelcoinDistributor.sol#L143 https://github.com/sherlock-audit/2024-01-telcoin/blob/main/telcoin-audit/contracts/protocol/core/TelcoinDistributor.sol#L210

Tool used

Manual Review

Recommendation

Set limitations for the challengePeriod value so that it can not overflow on the checks highlighted.

nevillehuang commented 9 months ago

Invalid, admins are trusted entities trusted to set appropriate challenge periods for proposals