sherlock-audit / 2022-10-merit-circle-judging

1 stars 0 forks source link

defsec - Incompatibility With Rebasing/Deflationary/Inflationary tokens #18

Closed sherlock-admin closed 2 years ago

sherlock-admin commented 2 years ago

defsec

medium

Incompatibility With Rebasing/Deflationary/Inflationary tokens

Summary

The Merit Circle protocol do not appear to support rebasing/deflationary/inflationary tokens whose balance changes during transfers or over time. The necessary checks include at least verifying the amount of tokens transferred to contracts before and after the actual transfer to infer any fees/interest.

Vulnerability Detail

The Merit Circle protocol do not appear to support rebasing/deflationary/inflationary tokens whose balance changes during transfers or over time. The necessary checks include at least verifying the amount of tokens transferred to contracts before and after the actual transfer to infer any fees/interest.

Suppose 100 USDT is transferred via safeTransferFrom() to the TimeLockPool contract. And a fee is applied (currently 0, but might be changed in the future). Then you might receive 99.99 USDT Now you try to do _mint(_receiver, mintAmount); ( 100 USDT ), minting amount will be less than excepted.

Impact

The internal accounting system of the liquidity would be inaccurate or break, affecting the protocol operation.

Code Snippet

https://github.com/sherlock-audit/2022-10-merit-circle/blob/main/merit-liquidity-mining/contracts/TimeLockPool.sol#L94

    function deposit(uint256 _amount, uint256 _duration, address _receiver) external override {
        if (_amount == 0) {
            revert ZeroAmountError();
        }
        // Don't allow locking > maxLockDuration
        uint256 duration = _duration.min(maxLockDuration);
        // Enforce min lockup duration to prevent flash loan or MEV transaction ordering
        duration = duration.max(MIN_LOCK_DURATION);

        depositToken.safeTransferFrom(_msgSender(), address(this), _amount);

        uint256 mintAmount = _amount * getMultiplier(duration) / 1e18;

        depositsOf[_receiver].push(Deposit({
            amount: _amount,
            shareAmount: mintAmount,
            start: uint64(block.timestamp),
            end: uint64(block.timestamp) + uint64(duration)
        }));

        _mint(_receiver, mintAmount);
        emit Deposited(_amount, duration, _receiver, _msgSender());
    }

Tool used

Manual Review

Recommendation

Determine the transferred amount by subtracting the before & after balance. Have a procedure to don't allow the use of rebasing/inflation/deflation underlying tokens.