Open code423n4 opened 2 years ago
Good report, although very low risk as the preconditions are extremely unlikely. Will take into account the suggestion by adding a comment to the function. Thank you.
I would probably downgrade to QA, but the warden does a good job of proving the point out with examples. Will leave as M
Lines of code
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/TRSRY.sol#L105-L112 https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Operator.sol#L330
Vulnerability details
Impact
One can repay loan to the treasury with the value from the Operator::swap
Condition:
Proof of Concept
The below code snippet shows a part of proof of concept for reentrancy attack, which is based on
src/test/policies/Operator.t.sol
. The full test code can be found here, and git diff from theOperator.t.sol
.Let's say that the reserve token implements ERC777 with the hook for the sender (see weird erc20). If the attacker can take debt of the reserve currency for the attack contract
Reenterer
, the contract can callOlympusTreasury::repayLoan
and in the middle of repay callOperator::swap
function. Theswap
function will modify the reserve token balance of treasury and the amount the attacker swapped will be also be used for therepayLoan
.In the below example, the attacker has debt of 1e18, and repays 1e17. But since the
swap
function is called in therepayLoan
, the debt is reduced 1e17 more then it should. And the swap happened as expected so the attack has the corresponding ohm token.Cause
The
repayLoan
, in the line 110 below, calls thesafeTransferFrom
. The balance before and after are compared to determine how much of debt is paid. So, if thesafeTranferFrom
can modify the balance, the attacker can profit from it.In the
swap
function, if the amount in token is reserve, the payment token to buy ohm will be paid to the treasury. It gives to an opportunity to modify the balance.Although both of
Operator::swap
andOlympusTreasury::repayLoan
havenonReentrant
modifier, it does not prevent as they are two different contracts.Tools Used
foundry
Recommended Mitigation Steps
The deposit logic in the
OlympusTreasury::repayLoan
was trying to handle nonstandard tokens, such as fee-on-transfer. But by doing so introduced an attack vector for tokens with ERC777. If the reserve token should be decided in the governance, it should be clarified, which token standards can be used safely.