Platform: Code4rena
Start Date: 23/06/2023
Pot Size: $60,500 USDC
Total HM: 31
Participants: 132
Period: 10 days
Judge: 0xean
Total Solo HM: 10
Id: 254
League: ETH
Rank: 111/132
Findings: 3
Award: $16.78
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: hl_
Also found by: 0xRobocop, Co0nan, CrypticShepherd, DedOhWale, Iurii3, Kenshin, Musaka, OMEN, RedOneN, SpicyMeatball, Toshii, Vagner, bytes032, cccz, gs8nrv, hl_, kenta, lanrebayode77, mahdikarimi, max10afternoon, peanuts, pep7siup
5.5262 USDC - $5.53
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraPeUSDVaultBase.sol#L125-L146 https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraEUSDVaultBase.sol#L154-L176 https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraEUSDVaultBase.sol#L187-L211
The liquidation functions in both contracts need to take an address of a provider, from which it will be taken the eusdAmount
or peusdAmount
after it verifies that the provider allowance to the contract is greater than 0. Basically before calling the liquidation function, the provider needs to approve the contract some amount of tokens so the function _repay
can transferFrom
the amount of borrowed tokens https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraPeUSDVaultBase.sol#L192-L210
After that the liquidation
functions checks if provider
is the same as msg.sender
and transfer the assets to the provider if it is the same as msg.sender
or it will give a small amount to msg.sender
and the rest to provider https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraPeUSDVaultBase.sol#L138-L144
The problem relies in the fact that anybody can front-run the liquidation function getting a small amount of rewards, without risking or losing anything beside the higher gas fee paid.
Take this simple case :
provider
address to Alice oneManual review
Do more checks in the liquidation function or change how the function work so it is not that easily front-runnable
Timing
#0 - c4-pre-sort
2023-07-08T23:58:04Z
JeffCX marked the issue as duplicate of #532
#1 - c4-judge
2023-07-28T15:39:44Z
0xean marked the issue as satisfactory
#2 - c4-judge
2023-07-28T19:41:44Z
0xean changed the severity to 2 (Med Risk)
🌟 Selected for report: hl_
Also found by: 0xRobocop, Co0nan, CrypticShepherd, DedOhWale, Iurii3, Kenshin, Musaka, OMEN, RedOneN, SpicyMeatball, Toshii, Vagner, bytes032, cccz, gs8nrv, hl_, kenta, lanrebayode77, mahdikarimi, max10afternoon, peanuts, pep7siup
5.5262 USDC - $5.53
The function _repay
is used to repay the borrowed PeUSD in the cases of liquidation or simple repayment. The function checks if the borrowed
amount of the user + totalFee
is greater or equal to the _amount
wanted to be repayed. If that's not the case the amount
would be equal to borrowed
+ totalFee
as can be seen here https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraPeUSDVaultBase.sol#L196
The problem relies in the fact that after it will transfer the totalFee
to the configurator
and burn the difference between the amount
and totalFee
, it will subtract from the borrowed[_onBehalfOf]
the amount
value https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraPeUSDVaultBase.sol#L206
but in the case where the amount
it will be equal to borrowed[_onBehalfOf]
+ totalFee
than the amount
will always be greater than borrowed[_onBehalfOf]
which will result in revert 100% of the time because of the underflow.
Manual review
Change the logic of the function so the subtraction would not revert in the case where amount
is equal to borrowed[_onBehalfOf]
+ totalFee
Under/Overflow
#0 - c4-pre-sort
2023-07-10T13:43:21Z
JeffCX marked the issue as duplicate of #532
#1 - c4-judge
2023-07-28T15:39:43Z
0xean marked the issue as satisfactory
#2 - c4-judge
2023-07-28T19:41:44Z
0xean changed the severity to 2 (Med Risk)
🌟 Selected for report: bytes032
Also found by: 0xMAKEOUTHILL, 0xgrbr, 0xkazim, 0xnacho, Arz, Co0nan, CrypticShepherd, Cryptor, HE1M, Iurii3, LaScaloneta, LokiThe5th, LuchoLeonel1, MrPotatoMagic, Musaka, Qeew, RedTiger, SovaSlava, Toshii, Vagner, a3yip6, azhar, bart1e, devival, hl_, jnrlouis, kutugu, peanuts, pep7siup, qpzm, smaul
1.3247 USDC - $1.32
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/LybraWbETHVault.sol#L35 https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/LybraRETHVault.sol#L47
The function getAssetPrice
is used multiple times to calculate different values, but in the cases of LybraRETHVault.sol
and LybraWbETHVault.sol
this function would revert because in both contracts it calls the wrong function in the BETH and RETH deployed contracts.
The function getAssetPrice
calculate the price of the collateral asset multiplying the price from the Oracle in _etherPrice
function with the value from the getExchangeRatio
for LybraRETHVault.sol
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/LybraRETHVault.sol#L47 and exchangeRatio
for LybraWbETHVault.sol
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/LybraWbETHVault.sol#L35 but the functions on the RETH and BETH contract are not named getExchangeRatio
and exchangeRatio
but getExchangeRate
and exchangeRate
as can be seen on etherscan https://etherscan.io/address/0xae78736Cd615f374D3085123A210448E74Fc6393#code#F1#L92
https://etherscan.io/address/0x523177fbe442afb70b401d06bb11ec7b8684ecee#code#F21#L256
Manual review
Change the name of the function to the ones on the deployed contracts so the getAssetPrice
for those two cases would not revert all the time
Other
#0 - c4-pre-sort
2023-07-08T23:58:31Z
JeffCX marked the issue as duplicate of #27
#1 - c4-judge
2023-07-28T17:14:12Z
0xean changed the severity to 2 (Med Risk)
#2 - c4-judge
2023-07-28T17:15:40Z
0xean marked the issue as satisfactory
🌟 Selected for report: 0xnev
Also found by: 0xRobocop, 0xbrett8571, 0xkazim, 0xnacho, 3agle, 8olidity, ABAIKUNANBAEV, Bauchibred, Co0nan, CrypticShepherd, D_Auditor, DelerRH, HE1M, Iurii3, Kaysoft, MrPotatoMagic, RedOneN, RedTiger, Rolezn, SanketKogekar, Sathish9098, Timenov, Toshii, Vagner, bart1e, bytes032, codetilda, devival, halden, hals, kutugu, m_Rassska, naman1778, nonseodion, seth_lawson, solsaver, squeaky_cactus, totomanov, y51r, yudan, zaevlad
9.931 USDC - $9.93
The liquidation process in LybraPeUSDVaultBase.sol
uses getBadCollateralRatio
to see if the borrwers collateral ratio is less than vaultBadCollateralRatio
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/base/LybraPeUSDVaultBase.sol#L128
calling the getBadCollateralRatio
function in LybraConfigurator.sol
. The function checks if the vaultBadCollateralRatio
variable is 0 and if that's the case it get the value from the subtraction of vaultSafeCollateralRatio
and 1e19 https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/configuration/LybraConfigurator.sol#L339 but as we can see above vaultSafeCollateralRatio
can also be uninitialized which in the case of getSafeCollateralRatio
function would return 160 * 1e18 https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/configuration/LybraConfigurator.sol#L334 but for getBadCollateralRatio
this would underflow and revert since the value of getSafeCollateralRatio
would be 0.
If a person can be liquidated but the values of the 2 variables are not yet initialized, since they can be set just by the Timelock or the DAO, the function would revert all the time because of the subtraction.
Manual review
Instead of using the variable vaultSafeCollateralRatio
to do the subtraction in getBadCollateralRatio
use the function getSafeCollateralRatio
which would return for sure a value greater than 1e19, making the function not revert.
Under/Overflow
#0 - c4-pre-sort
2023-07-04T15:26:32Z
JeffCX marked the issue as primary issue
#1 - c4-sponsor
2023-07-18T08:25:56Z
LybraFinance marked the issue as sponsor disputed
#2 - LybraFinance
2023-07-18T08:26:01Z
We will ensure that the relevant configurations are in place when the system is running.
#3 - c4-judge
2023-07-26T16:43:34Z
0xean changed the severity to QA (Quality Assurance)
#4 - c4-judge
2023-07-28T18:06:26Z
0xean marked the issue as grade-b
#5 - c4-sponsor
2023-07-29T11:15:52Z
LybraFinance marked the issue as sponsor acknowledged