code-423n4 / 2023-12-revolutionprotocol-findings

3 stars 2 forks source link

`ERC20TokenEmitter` contract: governance token price will be increased with each upgrade #510

Open c4-bot-8 opened 10 months ago

c4-bot-8 commented 10 months ago

Lines of code

https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/ERC20TokenEmitter.sol#L105 https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/ERC20TokenEmitter.sol#L271-L281

Vulnerability details

Impact

Proof of Concept

ERC20TokenEmitter.initialize function/L105

startTime = block.timestamp;

ERC20TokenEmitter.getTokenQuoteForPayment function

   function getTokenQuoteForPayment(uint256 paymentAmount) external view returns (int gainedX) {
        require(paymentAmount > 0, "Payment amount must be greater than 0");
        // Note: By using toDaysWadUnsafe(block.timestamp - startTime) we are establishing that 1 "unit of time" is 1 day.
        // solhint-disable-next-line not-rely-on-time
        return
            vrgdac.yToX({
                timeSinceStart: toDaysWadUnsafe(block.timestamp - startTime),
                sold: emittedTokenWad,
                amount: int(((paymentAmount - computeTotalReward(paymentAmount)) * (10_000 - creatorRateBps)) / 10_000)
            });
    }

Tools Used

Manual Review.

Recommended Mitigation Steps

Preserve the previous value of startTime when re-initializing the contract:

    function initialize(
        address _initialOwner,
        address _erc20Token,
        address _treasury,
        address _vrgdac,
        address _creatorsAddress
    ) external initializer {
        require(msg.sender == address(manager), "Only manager can initialize");

        __Pausable_init();
        __ReentrancyGuard_init();

        require(_treasury != address(0), "Invalid treasury address");

        // Set up ownable
        __Ownable_init(_initialOwner);

        treasury = _treasury;
        creatorsAddress = _creatorsAddress;
        vrgdac = VRGDAC(_vrgdac);
        token = NontransferableERC20Votes(_erc20Token);
-       startTime = block.timestamp;
+       if(startTime == 0) startTime = block.timestamp;
    }

Assessed type

Context

c4-pre-sort commented 10 months ago

raymondfam marked the issue as insufficient quality report

c4-pre-sort commented 10 months ago

raymondfam marked the issue as primary issue

raymondfam commented 10 months ago

startTime == 0 would be true on the upgraded contract.

c4-judge commented 10 months ago

MarioPoneder changed the severity to QA (Quality Assurance)

MarioPoneder commented 10 months ago

@rocketman-21 Tagging for visibility.

MarioPoneder commented 10 months ago

Anyways, QA because affecting future contract implementation.

c4-judge commented 10 months ago

MarioPoneder marked the issue as grade-b

rocketman-21 commented 10 months ago

this is fair - appreciate the tag, implemented fix