Platform: Code4rena
Start Date: 17/02/2022
Pot Size: $75,000 USDC
Total HM: 20
Participants: 39
Period: 7 days
Judges: moose-code, JasoonS
Total Solo HM: 13
Id: 89
League: ETH
Rank: 11/39
Findings: 4
Award: $3,138.50
π Selected for report: 1
π Solo Findings: 1
On Oracle.sol#L115, we are using latestRoundData
, but there are no validations that the data is not stale.
The current code is:
(uint80 round, int256 latestPrice, , uint256 latestTimestamp, ) = _aggregator.latestRoundData(); finalPrice = uint256(latestPrice); if (latestPrice < 0) { requireEnoughHistory(round); (round, finalPrice, latestTimestamp) = getRoundData(_aggregator, round - 1); } return (round, finalPrice, latestTimestamp);
But is missing the checks to validate the data is stale
(uint80 round, int256 latestPrice, , uint256 latestTimestamp, answeredInRound) = _aggregator.latestRoundData(); require(latestPrice > 0, "Chainlink price <= 0"); require(latestTimestamp != 0, "Incomplete round"); require(answeredInRound >= round, "Stale price");
This could affect in all the logic, including funds.
#0 - atvanguard
2022-02-24T06:02:04Z
Duplicate of #46
#1 - moose-code
2022-03-09T20:54:40Z
Marking as a duplicate of #9 (i.e. lumping them together)
π Selected for report: 0x1f8b
2785.5118 USDC - $2,785.51
The contract use two governance model, one looks hidden.
The VUSD contract uses VanillaGovernable
but inherits from ERC20PresetMinterPauserUpgradeable
and this contract uses roles to use some administrative methods like pause
or mint
.
This two-governance model does not seem necessary and can hide or raise suspicion about a rogue pool, thus damaging the user's trust.
Unify governance in only one, VanillaGovernable or role based.
#0 - moose-code
2022-03-06T09:28:28Z
Yes a good suggestion to keep governance more tightly coupled. OZ has AccessControlledAndUpgradeable which is really nice. Various roles for varying level of admin functionality. Allows tighter controls on more controversial items and easier control on less controversial items.
π Selected for report: defsec
Also found by: 0v3rf10w, 0x0x0x, 0x1f8b, 0xwags, CertoraInc, Dravee, IllIllI, Meta0xNull, Nikolay, Omik, WatchPug, bobi, cccz, csanuragjain, danb, gzeon, hubble, hyh, itsmeSTYJ, jayjonah8, kenta, kirk-baird, leastwood, pauliax, peritoflores, rfa, robee, sorrynotsorry, ye0lde
157.6711 USDC - $157.67
LOW
"@openzeppelin/contracts": "4.2.0", "@openzeppelin/contracts-upgradeable": "4.3.2",
Governable
and can be paused, so a denial of service could happend if the keys are compromised or the issue number 3 happens.safeTransferFrom
, therefore, the amount received by VUSD
will be less than the expected.
Some tokens may implement a fee during transfers, this is the case of USDT, even though the project has currently set it to 0. So, the transferFrom
function would return 'true' despite receiving less than expected.The logic is while (i < withdrawals.length && (i - start) <= maxWithdrawalProcesses) {
If maxWithdrawalProcesses=0
and start=0
then i=0
. So (0-0)<=0
== true
But the expected maxWithdrawalProcesses is zero.
#0 - atvanguard
2022-02-26T07:33:46Z
1 issue is a duplicate of #21 , disputing the rest.
#1 - moose-code
2022-03-05T15:59:07Z
https://github.com/OpenZeppelin/openzeppelin-contracts/releases upgrading open zeppelin can be considered. Its good
87.3994 USDC - $87.40
i++
to ++i
in order to save some opcodes:immutable
keyword for the following variables:marginAccount
and vusd
in MarginAccountHelper.sol#L15-L16PRECISION.toInt256()
because PRECISION
is a constant