Omniscia Kyo Finance Audit

SmoothTokenStreamConsumer Manual Review Findings

SmoothTokenStreamConsumer Manual Review Findings

STS-01M: Discrepancy of Mathematical Formulae

Description:

The SmoothTokenStreamConsumer::_computeCurve calculation when it comes to distributions in between two timepoints deviates from its mathematical representation in the smooth_tokenstream_consumer.md file.

Specifically, the code branch that includes the currentPendingInput - lastPendingInput delta will solely trigger when timeElapsed is non-zero; a trait that is incorrect.

As timeElapsed approaches zero, the r2 term approaches 1e18 meaning that a case whereby timeElapsed is 0 and currentPendingInput is greater than the lastPendingInput should result in an increase of the lockedAmount by currentPendingInput - lastPendingInput.

Impact:

The special case whereby the time delta is 0 and a pending input has been detected will be handled improperly as it would not be distributed adequately.

Example:

contracts/reward/SmoothTokenStreamConsumer.sol
56function _computeCurve(address token, uint128 sourcePendingInput) internal view returns (uint128 lockedAmount, uint128 pendingAmount, uint128 currentPendingInput) {
57 int256 timeElapsed = int256(block.timestamp - lastUpdateTime[token]);
58 int256 r = wadExp(logDecayRate * timeElapsed);
59 currentPendingInput = sourcePendingInput;
60 uint128 lastPendingInput = lastPendingInputs[token];
61
62 lockedAmount = uint128(uint256(lastLockedAmounts[token]) * uint256(r)) / 1e18;
63
64 if (timeElapsed > 0 && currentPendingInput > lastPendingInput) {
65 int256 r2 = ((r - 1e18) * 1e18) / (logDecayRate * timeElapsed);
66 lockedAmount += uint128((uint256(currentPendingInput - lastPendingInput) * uint256(r2)) / 1e18);
67 }
68
69 if (lockedAmount <= currentPendingInput) pendingAmount = currentPendingInput - lockedAmount;
70}

Recommendation:

We advise this change to be incorporated to the codebase so as to ensure that the code properly implements the mathematical formulae outlined in its documentation.

Alleviation (17c8d4e59f398021156f6f9657ff278aae0462ae):

The code was updated to match the formulae depicted in the smooth_tokenstream_consumer.md file, alleviating this exhibit in full.

STS-02M: Improper Evaluation of Last Update Time

TypeSeverityLocation
Logical FaultSmoothTokenStreamConsumer.sol:
I-1: L57
I-2: L92

Description:

The SmoothTokenStreamConsumer will improperly evaluate newly introduced token entries to its system as they will all possess a zero-value lastUpdateTime (due to the variable being private and thus impossible to mutate beyond the SmoothTokenStreamConsumer contract) and will thus calculate timeElapsed incorrectly when calculating the curve as well as token input per second.

Impact:

The system will over-estimate the first time elapsed measurement of a token due to not containing an update time reset mechanism.

Example:

contracts/reward/SmoothTokenStreamConsumer.sol
56function _computeCurve(address token, uint128 sourcePendingInput) internal view returns (uint128 lockedAmount, uint128 pendingAmount, uint128 currentPendingInput) {
57 int256 timeElapsed = int256(block.timestamp - lastUpdateTime[token]);
58 int256 r = wadExp(logDecayRate * timeElapsed);
59 currentPendingInput = sourcePendingInput;
60 uint128 lastPendingInput = lastPendingInputs[token];
61
62 lockedAmount = uint128(uint256(lastLockedAmounts[token]) * uint256(r)) / 1e18;
63
64 if (timeElapsed > 0 && currentPendingInput > lastPendingInput) {
65 int256 r2 = ((r - 1e18) * 1e18) / (logDecayRate * timeElapsed);
66 lockedAmount += uint128((uint256(currentPendingInput - lastPendingInput) * uint256(r2)) / 1e18);
67 }
68
69 if (lockedAmount <= currentPendingInput) pendingAmount = currentPendingInput - lockedAmount;
70}

Recommendation:

We advise the code to default to a value of 0 for the timeElapsed calculation if the token has not been updated in the system before, ensuring that timeElapsed calculations assume an elapsed time of 0 if the token has been newly introduced to the system.

Alleviation (17c8d4e59f398021156f6f9657ff278aae0462ae):

The time elapsed delta in both the curve computations and the token input per second calculations was updated to yield 0 if a last update time has not been observed, addressing this exhibit in full.