Platform: Code4rena
Start Date: 25/08/2022
Pot Size: $75,000 USDC
Total HM: 35
Participants: 147
Period: 7 days
Judge: 0xean
Total Solo HM: 15
Id: 156
League: ETH
Rank: 43/147
Findings: 2
Award: $401.57
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: GalloDaSballo
347.2615 DAI - $347.26
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Heart.sol#L106 https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Heart.sol#L112 https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/libraries/TransferHelper.sol#L23
If the Heart.sol
contract's balance of rewardToken ever falls below the reward amount, the heartbeat will fail and the full protocol's metrics will be thrown off.
The beat()
function contains a call to _issueReward(msg.sender)
.
This function uses the TransferHelper
library to call rewardToken.safeTransfer(to_, reward);
.
In the helper function, the transfer is made using a low level call and fails unless the call returns a success boolean.
(bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(ERC20.transfer.selector, to, amount) ); require(success && (data.length == 0 || abi.decode(data, (bool))), "TRANSFER_FAILED");
As a result, the full beat()
function will fail.
VS Code
Update the _issueReward()
function to check the reward amount and the current balance, and send the minimum value out of these two options.
function _issueReward(address to_) internal { uint bal = rewardToken.balanceOf(address(this)); uint toSend = reward > bal ? bal : reward; rewardToken.safeTransfer(to_, toSend); emit RewardIssued(to_, reward); }
#0 - Oighty
2022-09-07T20:36:30Z
Keepers will be able to check the contract balance and the reward amount prior to calling the contract to avoid failed transactions as a result of a low reward balance. We acknowledge that the fails could happen, but that is typical for reward contracts which do not mint tokens.
#1 - Oighty
2022-09-07T20:42:28Z
After reviewing #378 , I changed my mind about this one due to the anti-DOS characteristics of using a min implementation.
#2 - 0xean
2022-09-19T14:34:39Z
closing as duplicate of #378
🌟 Selected for report: zzzitron
Also found by: 0x040, 0x1f8b, 0x52, 0x85102, 0xDjango, 0xNazgul, 0xNineDec, 0xSky, 0xSmartContract, 0xkatana, 8olidity, Aymen0909, Bahurum, BipinSah, Bnke0x0, CRYP70, CertoraInc, Ch_301, Chandr, Chom, CodingNameKiki, Deivitto, DimSon, Diraco, ElKu, EthLedger, Funen, GalloDaSballo, Guardian, IllIllI, JansenC, Jeiwan, Lambda, LeoS, Margaret, MasterCookie, PPrieditis, PaludoX0, Picodes, PwnPatrol, RaymondFam, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, StevenL, The_GUILD, TomJ, Tomo, Trust, Waze, __141345__, ajtra, ak1, apostle0x01, aviggiano, bin2chen, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, cccz, ch13fd357r0y3r, cloudjunky, cryptphi, csanuragjain, d3e4, datapunk, delfin454000, devtooligan, dipp, djxploit, durianSausage, eierina, enckrish, erictee, fatherOfBlocks, gogo, grGred, hansfriese, hyh, ignacio, indijanc, itsmeSTYJ, ladboy233, lukris02, martin, medikko, mics, natzuu, ne0n, nxrblsrpr, okkothejawa, oyc_109, p_crypt0, pfapostol, prasantgupta52, rajatbeladiya, rbserver, reassor, ret2basic, robee, rokinot, rvierdiiev, shenwilly, sikorico, sorrynotsorry, tnevler, tonisives, w0Lfrum, yixxas
54.3128 DAI - $54.31
The getLoan()
function in the TRSRY.sol
contract is a way for users to withdraw approved loans from the protocol, which can be repaid with repayLoan()
.
No policies have permission to call this function, and it appears it was intended to be publicly callable, but it has the permissioned
modifier, so it is functionally useless.
Without the getLoan()
function, repayLoan()
is functionally useless as well.
Checking the permissions set in each of the policies, there is no policy that has permission to call getLoan()
.
The permissioned
modifier requires that the function is only called by policies that have been pre-approved.
/// @notice Modifier to restrict which policies have access to module functions. modifier permissioned() { if (!kernel.modulePermissions(KEYCODE(), Policy(msg.sender), msg.sig)) revert Module_PolicyNotPermitted(msg.sender); _; }
As a result, this function cannot be called under any circumstances.
VS Code
Remove the permissioned
modifier from the getLoan()
function.
#0 - 0xLienid
2022-09-06T13:57:44Z
The system is designed around the ability to add and remove policies in the future. The fact there is not a policy using this feature on launch does not preclude its future use and need for permissioning.
#1 - 0xean
2022-09-16T22:38:31Z
Downgrading to QA, sponsors may want to consider documenting that its intended for future use.