Platform: Code4rena
Start Date: 20/01/2023
Pot Size: $90,500 USDC
Total HM: 10
Participants: 59
Period: 7 days
Judge: Picodes
Total Solo HM: 4
Id: 206
League: ETH
Rank: 15/59
Findings: 1
Award: $837.80
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: rbserver
Also found by: 0x1f8b, 0xAgro, 0xGusMcCrae, 0xSmartContract, Awesome, Breeje, DadeKuma, Diana, IllIllI, Josiah, Moksha, RaymondFam, Rolezn, SaeedAlipoor01988, Udsen, Viktor_Cortess, brgltd, btk, chaduke, cryptonue, ddimitrov22, delfin454000, descharre, fatherOfBlocks, georgits, hansfriese, lukris02, luxartvinsec, martin, matrix_0wl, mookimgo, oberon, popular00, shark, tnevler
837.804 USDC - $837.80
The protocol does 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.
Executing transfers and computing internal booking state variables with the same values.
Add the necessary calculations to use rebasing/deflationary/inflationary tokens. If these tokens are not intended to be supported by the protocol, consider adding comments on the project for clarification.
Pool.sol
Most casting operations in the project are using the SafeCast.sol
library, with the exception of Pool.sol
.
Consider using SafeCast.sol
inside Pool.sol
. Otherwise, the protocol can be subject of silent overflows resulting in accounting issues.
TimewapV2Pool.initialize()
It's possible for an attacker to call initialize()
before the contract owner.
In the best case, the owner is forced to waste gas and re-deploy. In the worst case, the owner does not notice that his/her call reverts, and everyone starts using a contract under the control of an attacker.
Consider adding access control on initialize()
so that it can only be called by the contract owner (that address that executed the constructor code) or trusted addresses.
TimeswapV2Option
burn()
and collect()
functionsThe functions burn()
and collect()
for TimeswapV2Option.sol
are open to reentrancy. The comment on Process.sol L27 mentions reentrancy protection for process
. However the option
state variable inside TimeswapV2Option.sol
is updated after the external transfers.
Consider adding a reentrancy guard on burn()
and collect()
. Also, consider making state updates before external calls.
Locking the pragma helps to ensure that contracts do not accidentally get deployed using an outdated compiler version.
Note that pragma statements can be allowed to float when a contract is intended for consumption by other developers, as in the case with contracts in a library or a package.
Using the fixed latest stable version (v.0.8.17) helps to ensure the compiler has the latest security fixes and the latest features, e.g. for versions >=0.8.10, external calls skip contract existence checks if the external call has a return value.
https://github.com/code-423n4/2023-01-timeswap/blob/main/packages/v2-pool/src/TimeswapV2Pool.sol#L2
Multiple functions in the project emit an event as the last statement. Wherever possible, consider emitting events before external calls. In case of reentrancy, funds are not at risk (for external call + event ordering), however emitting events after external calls can damage frontends and monitoring tools in case of reentrancy attacks.
Iterating state/storage variables from 0 to length -1 can run out of gas if the state/storage variable has too many items. Wherever possible, consider adding a slice functionality on the functions calling Process.updateProcess()
, so that Process.updateProcess()
can be called in chunks and accepts a startIndex
and an endIndex
variables.
to
in Pool.transferLiquidity()
https://github.com/code-423n4/2023-01-timeswap/blob/main/packages/v2-pool/src/structs/Pool.sol#L158
The following packages used by the system are not published on npm
https://www.npmjs.com/search?q=@timeswap-labs/v2-option https://www.npmjs.com/search?q=@timeswap-labs/v2-library https://www.npmjs.com/search?q=@timeswap-labs/v2-library
A vulnerability related to this on the last Timeswap contest.
It does not seem to be a vulnerability at this point, since npm doesn't allow for different organizations to have the same name.
However, I would still recommend to publish the mentioned packages on npm. E.g. is npm ever allows for different companies to register the same name, an attacker could upload malicious code for @timeswap-labs/v2-option and execute malicious code on users machines.
https://github.com/code-423n4/2023-01-timeswap/blob/main/packages/v2-library/src/Math.sol#L88-L90
Consider adding NATSPEC on all external/public functions to improve documentation.
The solidity documentation recommends the following order for functions:
constructor external public internal private
The instance bellow shows an different ordering being used in TimeswapV2Pool.sol
.
The solidity documentation recommends a maximum of 120 characters.
Consider adding a limit of 120 characters or less to prevent large lines.
https://github.com/code-423n4/2023-01-timeswap/blob/main/packages/v2-pool/src/TimeswapV2Pool.sol#L32
Repeated validation statements can be converted into a function modifier to improve code reusability.
#0 - c4-judge
2023-02-01T23:43:31Z
Picodes marked the issue as grade-b
#1 - c4-judge
2023-02-01T23:43:54Z
Picodes marked the issue as grade-a