Platform: Code4rena
Start Date: 01/07/2021
Pot Size: $100,000 USDC
Total HM: 10
Participants: 7
Period: 7 days
Judge: ghoulsol
Total Solo HM: 4
Id: 17
League: ETH
Rank: 6/7
Findings: 3
Award: $1,308.59
🌟 Selected for report: 2
🚀 Solo Findings: 0
a_delamo
I would recommend using latestRoundData instead of latestAnswer. This way we can run extra validations and makes sure that the data is okay.
( roundId, rawPrice, , updateTime, answeredInRound ) = AggregatorV3Interface(XXXX).latestRoundData(); require(rawPrice > 0, "Chainlink price <= 0"); require(updateTime != 0, "Incomplete round"); require(answeredInRound >= roundId, "Stale price");
// https://docs.chain.link/docs/developer-communications/ A new function latestRoundData has been added. It returns roundId, answer, startedAt, updatedAt, and answeredInRound. This allows consumers of reference data to make decisions around if the data is acceptable in a single function call (ex: if answeredInRound < roundId could indicate stale data).
#0 - flabble-gro
2021-07-14T20:25:09Z
Duplicate of #106
#1 - ghoul-sol
2021-07-26T01:30:11Z
Duplicate of #106 which means it's medium risk.
🌟 Selected for report: a_delamo
Also found by: 0xRajeev, GalloDaSballo, shw
38.4024 USDC - $38.40
a_delamo
The methods _stableToUsd
and _stableToLp
in theBuoy3Pool.sol
contract is duplicating the array unnecessarily and costing gas to the users.
function _stableToUsd(uint256[N_COINS] memory tokenAmounts, bool deposit) internal view returns (uint256) { require(tokenAmounts.length == N_COINS, "deposit: !length"); uint256[N_COINS] memory _tokenAmounts; for (uint256 i = 0; i < N_COINS; i++) { _tokenAmounts[i] = tokenAmounts[i]; } uint256 lpAmount = curvePool.calc_token_amount(_tokenAmounts, deposit); return _lpToUsd(lpAmount); } function _stableToLp(uint256[N_COINS] memory tokenAmounts, bool deposit) internal view returns (uint256) { require(tokenAmounts.length == N_COINS, "deposit: !length"); uint256[N_COINS] memory _tokenAmounts; for (uint256 i = 0; i < N_COINS; i++) { _tokenAmounts[i] = tokenAmounts[i]; } return curvePool.calc_token_amount(_tokenAmounts, deposit); }
🌟 Selected for report: a_delamo
210.7126 USDC - $210.71
a_delamo
In LifeGuard3Pool
and BaseVaultAdaptor
contracts, we are doing two approve calls when we could just use one. Doing two safeApprove calls with value = 0 and after value = max doesn't seem to provide any extra feature.
For example:
IERC20(_token).safeApprove(address(_vault), 0); IERC20(_token).safeApprove(address(_vault), type(uint256).max);
#0 - kitty-the-kat
2021-07-14T16:07:03Z
causes issues with usdt otherwise - could create separate logic to just deal with usdt, but is non-critical.