- Total Prize Pool: $90,500 USDC
- HM awards: $63,750 USDC
- QA report awards: $7,500 USDC
- Gas report awards: $3,750 USDC
- Judge + presort awards: $15,000 USDC
- Scout awards: $500 USDC
- Join C4 Discord to register
- Submit findings using the C4 form
- Read our guidelines for more details
- Starts January 20, 2023 20:00 UTC
- Ends January 27, 2023 20:00 UTC
The C4audit output for the contest can be found here within an hour of contest opening.
Note for C4 wardens: Anything included in the C4udit output is considered a publicly known issue and is ineligible for awards.
- A Timeswap pool uses the Duration Weighted Constant Product automated market maker (AMM) similar to Uniswap. It is designed specifically for pricing of Timeswap options. Let ๐ฅ be the borrow position with token0 as collateral, Let y be the borrow position with token1 as collateral. Let ๐ง be the lending position per second in the pool. Let ๐ be the duration of the pool, thus ๐๐ง is the total number of lending positions in the pool. Let ๐ฟ be the square root of the constant product of the AMM. (๐ = ๐ฟ2) Let ๐ผ be the marginal interest rate per second of the Short per total Long. (๐ฅ + ๐ฆ)๐ง =๐ฟ(square)
- The token does not conform to ERC20 standard, it uses ERC1155 standard.
- As this is a monorepo, where remappings are required for compilation there might be issues when running slither
- Link to whitepaper
Any test file i.e.**.t.sol
Timeswap V2 is a decentralized and oracle-less fixed maturity lending and borrowing protocol. It uses a triple constant product formula to determine the interest and collateral factor of every transaction.
Timeswap V2 has the following 4 packages in scope:
- v2-Option
- v2-Pool
- v2-Token
- v2-Library
In the following sections, we will be discussing each of the packages in greater depth.
Timeswap option is a close implementation of European option given the caveats of writing smart contracts in Ethereum.
Given a pair of tokens, defined as token0 and token1, the option is fully collateralized with either one of the tokens. When the option has locked token0, then it gives the holder the right but not the obligation to swap token1 for token0 before the maturity of the option. When the option has locked token1, then the holder can swap token0 for token1. When the swap is exercised, the token that is deposited becomes the new locked token of the option, giving the holder the right but not the obligation to swap the tokens back before maturity. This design gives the holder the ability to swap token0 and token1 back and forth at a given strike rate, for however many times before the expiry of the option.
A Timeswap pool is a protocol that gives the user the ability to swap Long 0 and/or Long 1 for Short Timeswap options, and vice versa. A Timeswap pool uses the Constant Product automated market maker (AMM) similar to Uniswap. It is designed specifically for the pricing of Timeswap options.
For lending, the user locks the Token0/Token1, mint Short option, and Long 0/Long 1 option. Then deposits the Long option minted to the pool, to withdraw more Short options from the pool.
For borrowing, the user lock the Token0/Token1, mint Short option, and Long 0/Long 1 option. Then deposits the Short option to the pool, to withdraw more Long 0/Long 1 options from the pool.
As one can see, all three products are fundamentally the same transactions with differences in how tokens are transferred. DEX protocol is used to make these transactions more fluid, whenever necessary.
The Timeswap v2 Protocol has 2 tokens that are implemented. The Timeswap V2 Token
and the Timeswap V2 Liquidity Token
The Timeswap V2 Liquidit Token
just holds the different liquidity position that user has, while the Timeswap V2 Token
is a representation of the amount of Long0, Long1, Short
that a user holds in a particular pool
- If you have a public code repo, please share it here: N/A
- How many contracts are in scope?: 70
- Total SLoC for these contracts?: 3659 [Solidity Metrics](https://github.com/ConsenSys/solidity-metrics) was used for calculating the nSLoC
- How many external imports are there?: 4
- How many separate interfaces and struct definitions are there for the contracts within scope?: 19 and 38
- Does most of your code generally use composition or inheritance?: Primarily inheritance, but composition is also leveraged up to some degree.
- How many external calls?: 0
- What is the overall line coverage percentage provided by your tests?: ~50 (`forge coverage` currently throws a "stack too deep" error on large codebases)
- Is there a need to understand a separate part of the codebase / get context in order to audit this part of the protocol?: No
- Please describe required context: N/A
- Does it use an oracle?: No
- Does the token conform to the ERC20 standard?: Yes
- Are there any novel or unique curve logic or mathematical models?: We use a 3 variable AMM - (x+y)z=k
- Does it use a timelock function?: No
- Is it an NFT?: No
- Does it have an AMM?: Yes
- Is it a fork of a popular project?: No
- Does it use rollups?: No
- Is it multi-chain?: No
- Does it use a side-chain?: Yes and it evm-compatible.
NOTE: Slither does not currently work on the repo. If you find a workaround, please share in the discord. The problem arises because slither looks for files in node_modules and contracts folder. To quickly test in slither something like symlinking folder with such name can help
Tests are currently work in progress To run the tests for code in each of the directories, run the following command at that directory
yarn
forge build
forge test
Coverage can be checked by the following command
forge coverage
Do note that the method employed by forge to calculate the coverage isn't very accurate as it takes into account individual testing of helper and utility functions. Wherever felt necessary and possible, we have included tests for such functions by wrapping them.
Contract | Function | Purpose |
---|---|---|
packages/v2-pool/src/TimeswapV2Pool.sol | addPoolEnumerationIfNecessary |
Implementing Reentrancy Logic |
packages/v2-pool/src/TimeswapV2Pool.sol | blockTimestamp |
Get time with respect to time forward |
packages/v2-pool/src/TimeswapV2Pool.sol | hasLiquidity |
Checks if pool has liquidity or not |
packages/v2-pool/src/TimeswapV2Pool.sol | collect |
Transfer long0, long1 and/or short positions to receipients |
packages/v2-pool/src/TimeswapV2Pool.sol | mint |
Main logic behind mint |
packages/v2-pool/src/TimeswapV2Pool.sol | burn |
Main logic behind burn |
packages/v2-pool/src/TimeswapV2Pool.sol | deleverage |
Main logic behind deleverage |
packages/v2-pool/src/TimeswapV2Pool.sol | leverage |
Main logic behind leverage |
Contract | Function | Purpose |
---|---|---|
packages/v2-pool/src/TimeswapV2Pool.sol | addPoolEnumerationIfNecessary |
Implementing Reentrancy Logic |
packages/v2-pool/src/TimeswapV2Pool.sol | blockTimestamp |
Get time with respect to time forward |
packages/v2-pool/src/TimeswapV2Pool.sol | hasLiquidity |
Checks if pool has liquidity or not |
packages/v2-pool/src/TimeswapV2Pool.sol | collect |
Transfer long0, long1 and/or short positions to receipients |
packages/v2-pool/src/TimeswapV2Pool.sol | mint |
Main logic behind mint |
packages/v2-pool/src/TimeswapV2Pool.sol | burn |
Main logic behind burn |
packages/v2-pool/src/TimeswapV2Pool.sol | deleverage |
Main logic behind deleverage |
packages/v2-pool/src/TimeswapV2Pool.sol | leverage |
Main logic behind leverage |