Platform: Code4rena
Start Date: 28/06/2022
Pot Size: $25,000 USDC
Total HM: 14
Participants: 50
Period: 4 days
Judge: GalloDaSballo
Total Solo HM: 7
Id: 141
League: ETH
Rank: 3/50
Findings: 5
Award: $2,842.76
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: ladboy233
2386.7697 USDC - $2,386.77
Detailed description of the impact of this finding.
Underlying asset price oracle for CToken in BaseV1-periphery is inaccuarte
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
function getUnderlyingPrice(CToken ctoken) external override view returns(uint price) { IBaseV1Pair pair; uint8 stable; bool stablePair; address underlying; if (compareStrings(ctoken.symbol(), "cCANTO")) { stable = 0; underlying = address(wcanto); } //set price statically to 1 when the Comptroller is retrieving Price else if (compareStrings(ctoken.symbol(), "cNOTE") && msg.sender == Comptroller) { return 1; // Note price is fixed to 1 }
we should not be return 1. 1 is 1 wei. we should be 10 ** 18
VIM
we can return 10 ** 18
#0 - GalloDaSballo
2022-08-16T15:56:01Z
The warden has shown what probably is a developer mistake, which will scale down the price of the cNOTE token to 1.
The sponsor confirms.
It should be noted that if cNOTE always returns 1e18 then the math for diff
will always be zero, meaning the interest will exclusively be dictated by baseRatePerYear
Because the sponsor confirms, and because the comments point to values "scaled by 1e18" I believe the finding to be valid, and since the "math is wrong", I do agree with High Severity
🌟 Selected for report: 0x52
Also found by: Chom, __141345__, csanuragjain, ladboy233
https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-core.sol#L71 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-core.sol#L166 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/NoteInterest.sol#L136
Detailed description of the impact of this finding.
Frequent price update make the project vulnerable to price oracle manipulation
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
in the code of stableswap V1 core,
// Capture oracle reading every 30 minutes uint constant periodSize = 0;
the periodSize defines how frequently the price is updated.
Then in _update function
if (timeElapsed > periodSize) { observations.push(Observation(blockTimestamp, reserve0CumulativeLast, reserve1CumulativeLast)); }
previously periodSize, which means the price is updated 30 minutes. If periodSzie is 0 then it means the price can be updated any time.
Hackers can manipulate the price and raise the interest in this favor.
change periodSize back to 1800.
#0 - nivasan1
2022-07-04T19:15:47Z
duplicate of #124
#1 - GalloDaSballo
2022-08-16T16:01:01Z
Dup of #124
70.4682 USDC - $70.47
https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L86 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L262 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L278 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L298 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L317 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L391 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L412 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L427 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L441 https://github.com/Plex-Engineer/lending-market-v2/blob/443a8c0fed3c5018e95f3881a31b81a555c42b2d/contracts/Stableswap/BaseV1-periphery.sol#L457
Detailed description of the impact of this finding.
The unused modifier that used to ensure that transaction deadline is met is removed. so the transaction order matters and if transaction lands latter block, the transaction is subject to frontend running (MEV)
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
modifier ensure(uint deadline) { //require(deadline >= block.timestamp, "BaseV1Router: EXPIRED"); _;
the modifier is removed. The modifier check to ensure transaction make the deadline requirement. also because the modifier commented.
the function that use the modifier also leave the deadline parameter unused.
function addLiquidity( address tokenA, address tokenB, bool stable, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external ensure(deadline)
Removing the modifier is bad if we consider the following case.
At block 1, the user wants to add 100 tokens B, 100 token B to main the liquidity ratio.
due to a gas issue or congested network, the transaction does not land in blockchain 2, it lands in blockchain 10.
say at block 5, a user already add 200 token A and 250 token B, then when the add liquidity function lands, the liqudity pool liqudity ratio
is unexpectedly affect.
same apply to remove and swap. Without check the deadline, the user may swap at bad rate in much later timeframe or remove a suboptimal amount of liquidity.
VIM
restore the modifier
#0 - GalloDaSballo
2022-08-14T19:49:34Z
Dup of #90
🌟 Selected for report: zzzitron
Also found by: 0v3rf10w, 0x1f8b, 0x29A, AlleyCat, Bnke0x0, Chom, Funen, JC, Lambda, Limbooo, Meera, Picodes, Sm4rty, TerrierLover, TomJ, __141345__, asutorufos, aysha, c3phas, cccz, defsec, fatherOfBlocks, grGred, hake, ignacio, ladboy233, mrpathfindr, oyc_109, rfa, sach1r0, samruna, slywaters, ynnad
44.8261 USDC - $44.83
// This is an evil token. Whenever an A -> B transfer is called, half of the amount goes to B // and half to a predefined C
can be removed.
can change
require(msg.sender == UniGovModAcct);
to
require(msg.sender == UniGovModAcct, "invalid account address");
https://github.com/Plex-Engineer/lending-market-v2/blob/main/contracts/WETH.sol
Developer can reuse the implementation of WETH from ethereum mainnet
https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2#code
can change
string public constant name = "Compound Governor Bravo";
to 'project Governor Bravo'
#0 - GalloDaSballo
2022-08-13T22:43:26Z
Valid NC
NC
Not sure how to evaluate without more details, in what way is the sponsor contract different?
NC
Neat report
3 NC
🌟 Selected for report: 0x1f8b
Also found by: 0x29A, 0xArshia, 0xKitsune, Bnke0x0, Chom, Fitraldys, Funen, JC, Lambda, Meera, Noah3o6, Picodes, RedOneN, Rohan16, Sm4rty, TerrierLover, TomJ, Tomio, Waze, ajtra, c3phas, cRat1st0s, defsec, durianSausage, fatherOfBlocks, grGred, hake, ladboy233, m_Rassska, mrpathfindr, oyc_109, rfa, ynnad
27.5044 USDC - $27.50
Can make the proposals public so in QueryProp,
function QueryProp(uint propId) public view returns(Proposal memory){ if (proposals[propId].id == propId) { return proposals[propId]; } return Proposal(0, "", "", new address[](0), new uint[](0), new string[](0), new bytes[](0)); }
We can just return proposals[propIds] to save gas.
The address can be declared as immutable to save gas.
function AddProposal() function QueryProp()
can be declared as external
quoteRemoveLiqudity can be declared as external
Withdraw function can be as external
setWETH can be changed from public to external.
Remove console log to save gas.
modifier ensure(uint deadline) { //require(deadline >= block.timestamp, "BaseV1Router: EXPIRED"); _; }
the modifier got commented out and did nothing.
#0 - GalloDaSballo
2022-08-14T20:50:18Z
2.1k from the immutable rest is negligible