Light ModeLight
Light ModeDark

One Bug Per Day

One H/M every day from top Wardens

Checkmark

Join over 1135 wardens!

Checkmark

Receive the email at any hour!

Ad

ERC20TokenEmitter will not work after a certain period of time

mediumCode4rena

Lines of code

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

Vulnerability details

Impact

The timeSinceStart in the vrgdac.xToY function will revert over a certain value, resulting in the ERC20TokenEmitter#buyToken function always revert.

Proof of Concept

Initialize the VRGDAC using the parameters in the test code.

solidity
VRGDAC vrgdac = new VRGDAC(1 ether, 1e18 / 10, 1_000 * 1e18);

The timeSinceStart is set to 394 days in the test code:

solidity
function testVRGDAC_time() public { VRGDAC vrgdac = new VRGDAC(1 ether, 1e18 / 10, 1_000 * 1e18); int256 x = vrgdac.yToX({ timeSinceStart: toDaysWadUnsafe(86400 * 400), sold: 1000 ether, amount: 1 ether }); uint256 xx = uint256(x); console.log(xx + 1); console.log(xx / 1e18); }

Run the forge test -vvvv, console to output:

[FAIL. Reason: UNDEFINED] testVRGDAC_time() (gas: 554525)
Traces:
  [106719] CounterTest::setUp() 
    ├─ [49499] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
    │   └─ ← 247 bytes of code
    ├─ [2390] Counter::setNumber(0) 
    │   └─ ← ()
    └─ ← ()

  [554525] CounterTest::testVRGDAC_time() 
    ├─ [517512] → new VRGDAC@0x2e234DAe75C793f67A35089C9d99245E1C58470b
    │   └─ ← 2578 bytes of code
    ├─ [3617] VRGDAC::yToX(400000000000000000000, 1000000000000000000000, 1000000000000000000) [staticcall]
    │   └─ ← "UNDEFINED"
    └─ ← "UNDEFINED"

Changing the timeSinceStart to toDaysWadUnsafe(86400 * 365) will work.

When this function is used in ERC20TokenEmitter#buyToken, the timeSinceStart is: block.timestamp-startTime

solidity
function buyTokenQuote(uint256 amount) public view returns (int spentY) { require(amount > 0, "Amount must be greater than 0"); return vrgdac.xToY({ timeSinceStart: toDaysWadUnsafe(block.timestamp - startTime), sold: emittedTokenWad, amount: int(amount) }); }

startTime is set during the initialization of the ERC20TokenEmitter contract:

solidity
function initialize( address _initialOwner, address _erc20Token, address _treasury, address _vrgdac, address _creatorsAddress ) external initializer { ..... startTime = block.timestamp; }

In other words, if the ERC20TokenEmitter contract is deployed and initialized and becomes unavailable after 400 days(400 days is the test value, the actual value will be affected by other parameters), calling the buyToken function will always revert.

Tools Used

vscode manual

Recommended Mitigation Steps

Optimize the vrgdac.yToX function, or set a minimum timeSinceStart value, which is used when the minimum is exceeded.

Assessed type

Math